From bf6365916dccc25ed77cf699cfba30894d4ef909 Mon Sep 17 00:00:00 2001
From: Neo-Desktop <321592+Neo-Desktop@users.noreply.github.com>
Date: Thu, 4 Jan 2024 16:32:18 -0800
Subject: [PATCH] total refactor, happy new year, ground level code for
automatic DPC selection, code is currently very much a work in progress, and
very much broken, we'll work through it
---
.clang-format | 4 +
.github/workflows/dos-djgpp.yml | 2 +-
.github/workflows/freebsd.yml | 38 +-
.github/workflows/linux.yml | 2 +-
.github/workflows/macos.yml | 2 +-
.github/workflows/windows.yml | 2 +-
.idea/remote-targets.xml | 14 +
.pre-commit-config.yaml | 25 +
CMakeLists.txt | 121 ++--
Dockerfile | 2 +-
Dockerfile.djgpp | 2 +-
Dockerfile.emscripten | 2 +-
Dockerfile.windows | 2 +-
keys.json | 932 +++++++++++++++++++++++------
src/cli.cpp | 717 ++++++++++------------
src/cli.h | 128 ++--
src/libumskt/confid/confid.cpp | 253 ++++----
src/libumskt/confid/confid.h | 168 +++---
src/libumskt/confid/divisor.cpp | 46 +-
src/libumskt/confid/polynomial.cpp | 24 +-
src/libumskt/confid/residue.cpp | 49 +-
src/libumskt/debugoutput.cpp | 15 +-
src/libumskt/libumskt.cpp | 145 ++++-
src/libumskt/libumskt.h | 18 +-
src/libumskt/pidgen2/PIDGEN2.cpp | 5 +-
src/libumskt/pidgen2/PIDGEN2.h | 30 +-
src/libumskt/pidgen3/BINK1998.cpp | 106 ++--
src/libumskt/pidgen3/BINK1998.h | 19 +-
src/libumskt/pidgen3/BINK2002.cpp | 116 ++--
src/libumskt/pidgen3/BINK2002.h | 20 +-
src/libumskt/pidgen3/PIDGEN3.cpp | 258 ++++++++
src/libumskt/pidgen3/PIDGEN3.h | 72 ++-
src/libumskt/pidgen3/key.cpp | 97 ---
src/libumskt/pidgen3/util.cpp | 131 ----
src/main.cpp | 42 +-
src/options.cpp | 318 ++++++++++
src/{header.h => options.h} | 51 +-
src/typedefs.h | 35 +-
src/windows/dllmain.cpp | 2 +-
src/windows/resource.h | 4 +-
src/windows/umskt.rc | Bin 4976 -> 4978 bytes
41 files changed, 2571 insertions(+), 1448 deletions(-)
create mode 100644 .idea/remote-targets.xml
create mode 100644 .pre-commit-config.yaml
create mode 100644 src/libumskt/pidgen3/PIDGEN3.cpp
delete mode 100644 src/libumskt/pidgen3/key.cpp
delete mode 100644 src/libumskt/pidgen3/util.cpp
create mode 100644 src/options.cpp
rename src/{header.h => options.h} (50%)
diff --git a/.clang-format b/.clang-format
index 674336e..b75ce03 100644
--- a/.clang-format
+++ b/.clang-format
@@ -213,4 +213,8 @@ WhitespaceSensitiveMacros:
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...
+---
+Language: Json
+BasedOnStyle: LLVM
+...
diff --git a/.github/workflows/dos-djgpp.yml b/.github/workflows/dos-djgpp.yml
index d28d938..a6d370d 100644
--- a/.github/workflows/dos-djgpp.yml
+++ b/.github/workflows/dos-djgpp.yml
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml
index bc75a3a..358c839 100644
--- a/.github/workflows/freebsd.yml
+++ b/.github/workflows/freebsd.yml
@@ -1,22 +1,22 @@
-# This file is a part of the UMSKT Project
- #
- # Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU Affero General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see .
- #
- # @FileCreated by techguy16 on 07/23/2023
- # @Maintainer techguy16
+# This file is a part of the UMSKT Project
+#
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# @FileCreated by techguy16 on 07/23/2023
+# @Maintainer techguy16
name: C/C++ CI (FreeBSD)
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index a2c790b..f60478f 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 74a3d68..cf689dc 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 99857d4..84177bb 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/.idea/remote-targets.xml b/.idea/remote-targets.xml
new file mode 100644
index 0000000..e8ce669
--- /dev/null
+++ b/.idea/remote-targets.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..a8f316b
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,25 @@
+# This file is a part of the UMSKT Project
+#
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# @FileCreated by Neo on 01/03/2024
+# @Maintainer Neo
+
+repos:
+- repo: https://github.com/pre-commit/mirrors-clang-format
+ rev: 'v15.0.7' # Use the sha / tag you want to point at
+ hooks:
+ - id: clang-format
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bcac58..dab7308 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@@ -34,28 +34,27 @@ SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS})
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
# macOS does not support static build
-if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(UMSKT_USE_SHARED_OPENSSL ON)
-endif()
+ENDIF ()
# neither does dos idk i'm trying random stuff
-if (DJGPP_WATT32)
+IF (DJGPP_WATT32)
SET(UMSKT_USE_SHARED_OPENSSL ON)
-endif()
+ENDIF ()
-IF(UMSKT_USE_SHARED_OPENSSL)
+IF (UMSKT_USE_SHARED_OPENSSL)
SET(OPENSSL_USE_STATIC_LIBS FALSE)
SET(OPENSSL_MSVC_STATIC_RT FALSE)
MESSAGE(STATUS "[UMSKT] Requesting dynamic version of OpenSSL")
-ELSE()
+ELSE ()
SET(OPENSSL_USE_STATIC_LIBS TRUE)
SET(OPENSSL_MSVC_STATIC_RT TRUE)
MESSAGE(STATUS "[UMSKT] Requesting static version of OpenSSL")
-ENDIF()
+ENDIF ()
-
-IF(DJGPP_WATT32)
+IF (DJGPP_WATT32)
SET(CMAKE_SYSTEM_NAME MSDOS)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
@@ -63,30 +62,30 @@ IF(DJGPP_WATT32)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} ${DJGPP_WATT32})
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS} ${WATT_ROOT}/lib)
-ENDIF()
+ENDIF ()
-if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- SET(BUILD_SHARED_LIBS ON)
- MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
-endif()
+IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ SET(BUILD_SHARED_LIBS ON)
+ MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
+ENDIF ()
# if we're compiling with MSVC, respect the DEBUG compile option
-IF(MSVC)
+IF (MSVC)
SET(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
- IF(NOT BUILD_SHARED_LIBS)
+ IF (NOT BUILD_SHARED_LIBS)
SET(CMAKE_CXX_FLAGS_RELEASE "/MT")
SET(CMAKE_CXX_FLAGS_DEBUG "/MTd")
- ELSE()
+ ELSE ()
SET(CMAKE_CXX_FLAGS_RELEASE "/MD")
SET(CMAKE_CXX_FLAGS_DEBUG "/MDd")
- ENDIF()
+ ENDIF ()
SET(CMAKE_EXE_LINKER_FLAGS "/INCREMENTAL:NO /NODEFAULTLIB:MSVCRT")
SET(CMAKE_ENABLE_EXPORTS ON)
SET(UMSKT_EXE_WINDOWS_EXTRA src/windows/umskt.rc)
SET(UMSKT_EXE_WINDOWS_DLL src/windows/dllmain.cpp)
-ENDIF()
+ENDIF ()
-IF(MUSL_STATIC)
+IF (MUSL_STATIC)
MESSAGE(STATUS "[UMSKT] Performing a fully static build using muslc")
SET(BUILD_SHARED_LIBS OFF)
SET(OPENSSL_USE_STATIC_LIBS TRUE)
@@ -96,47 +95,47 @@ IF(MUSL_STATIC)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc -static-libstdc++")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
-ENDIF()
+ENDIF ()
# find the system installed OpenSSL development library
FIND_PACKAGE(OpenSSL REQUIRED)
-IF(NOT OPENSSL_FOUND)
+IF (NOT OPENSSL_FOUND)
MESSAGE(SEND_ERROR "OpenSSL Development Libraries Not Found")
MESSAGE(SEND_ERROR "Please consult your package manager of choice to install the prerequisite")
MESSAGE(SEND_ERROR "The package name is commonly called libssl-dev or openssl-dev depending on distribution")
MESSAGE(FATAL_ERROR "Can not continue without OpenSSL")
-ENDIF()
+ENDIF ()
-IF(NOT MUSL_STATIC)
+IF (NOT MUSL_STATIC)
# if we found shared libraries - do the following:
IF (OPENSSL_USE_STATIC_LIBS)
- MESSAGE(STATUS "[UMSKT] requested static version of OpenSSL")
- if (NOT UMSKT_USE_SHARED_OPENSSL)
- MESSAGE(STATUS "[UMSKT] not asked for shared version of OpenSSL")
- ENDIF()
+ MESSAGE(STATUS "[UMSKT] requested static version of OpenSSL")
+ IF (NOT UMSKT_USE_SHARED_OPENSSL)
+ MESSAGE(STATUS "[UMSKT] not asked for shared version of OpenSSL")
+ ENDIF ()
- IF(MSVC)
- SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "ws2_32.lib")
- SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "crypt32.lib")
- MESSAGE(STATUS "[UMSKT] msvc adding ws2_32.lib crypt32.lib")
- ENDIF()
- ENDIF()
+ IF (MSVC)
+ SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "ws2_32.lib")
+ SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "crypt32.lib")
+ MESSAGE(STATUS "[UMSKT] msvc adding ws2_32.lib crypt32.lib")
+ ENDIF ()
+ ENDIF ()
STRING(REGEX MATCH "(\\.so|\\.dll|\\.dylib)$" OPENSSL_CRYPTO_SHARED "${OPENSSL_CRYPTO_LIBRARY}")
- IF(OPENSSL_CRYPTO_SHARED)
- MESSAGE(STATUS "[UMSKT] Detected Shared library version of OpenSSL")
- ELSE()
- MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL")
+ IF (OPENSSL_CRYPTO_SHARED)
+ MESSAGE(STATUS "[UMSKT] Detected Shared library version of OpenSSL")
+ ELSE ()
+ MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL")
- # static libcrypto on Fedora needs -lz at link time
- IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- FIND_PACKAGE(ZLIB REQUIRED)
- IF (NOT ZLIB_FOUND)
- MESSAGE(FATAL_ERROR "[UMSKT] linux static OpenSSL requires zlib")
- ENDIF()
- ENDIF()
- ENDIF()
-ENDIF()
+ # static libcrypto on Fedora needs -lz at link time
+ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ FIND_PACKAGE(ZLIB REQUIRED)
+ IF (NOT ZLIB_FOUND)
+ MESSAGE(FATAL_ERROR "[UMSKT] linux static OpenSSL requires zlib")
+ ENDIF ()
+ ENDIF ()
+ ENDIF ()
+ENDIF ()
# initalize cpm.CMake
INCLUDE(cmake/CPM.cmake)
@@ -185,39 +184,43 @@ CPMAddPackage(
### Resource compilation
CMRC_ADD_RESOURCE_LIBRARY(umskt-rc ALIAS umskt::rc NAMESPACE umskt keys.json)
-SET(LIBUMSKT_SRC src/libumskt/libumskt.cpp src/libumskt/pidgen3/BINK1998.cpp src/libumskt/pidgen3/BINK2002.cpp src/libumskt/pidgen3/key.cpp src/libumskt/pidgen3/util.cpp src/libumskt/confid/confid.cpp src/libumskt/confid/polynomial.cpp src/libumskt/confid/residue.cpp src/libumskt/confid/divisor.cpp src/libumskt/pidgen2/PIDGEN2.cpp src/libumskt/debugoutput.cpp)
+SET(LIBUMSKT_PIDGEN2 src/libumskt/pidgen2/PIDGEN2.cpp)
+SET(LIBUMSKT_PIDGEN3 src/libumskt/pidgen3/PIDGEN3.cpp src/libumskt/pidgen3/BINK1998.cpp src/libumskt/pidgen3/BINK2002.cpp)
+SET(LIBUMSKT_CONFID src/libumskt/confid/confid.cpp src/libumskt/confid/polynomial.cpp src/libumskt/confid/residue.cpp src/libumskt/confid/divisor.cpp)
+SET(LIBUMSKT_SRC src/libumskt/libumskt.cpp src/libumskt/debugoutput.cpp ${LIBUMSKT_PIDGEN2} ${LIBUMSKT_PIDGEN3} ${LIBUMSKT_CONFID})
+SET(UMSKT_CLI_SRC src/main.cpp src/cli.cpp src/options.cpp)
#### Separate Build Path for emscripten
IF (EMSCRIPTEN)
- ADD_EXECUTABLE(umskt ${LIBUMSKT_SRC})
+ ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${LIBUMSKT_SRC})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(umskt -static OpenSSL::Crypto cryptopp::cryptopp fmt)
SET(CMAKE_EXECUTABLE_SUFFIX ".html")
SET_TARGET_PROPERTIES(umskt PROPERTIES COMPILE_FLAGS "-Os -sEXPORTED_RUNTIME_METHODS=ccall,cwrap")
- SET_TARGET_PROPERTIES(umskt PROPERTIES LINK_FLAGS "-Os -sWASM=1 -sEXPORT_ALL=1 -sEXPORTED_RUNTIME_METHODS=ccall,cwrap --no-entry")
-ELSE()
+ SET_TARGET_PROPERTIES(umskt PROPERTIES LINK_FLAGS "-Os -sWASM=1 -sEXPORT_ALL=1 -sEXPORTED_RUNTIME_METHODS=ccall,cwrap --no-entry")
+ELSE ()
ADD_LIBRARY(_umskt ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_DIRECTORIES(_umskt PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(_umskt ${OPENSSL_CRYPTO_LIBRARIES} fmt ${UMSKT_LINK_LIBS})
### UMSKT executable compilation
- ADD_EXECUTABLE(umskt src/main.cpp src/cli.cpp ${UMSKT_EXE_WINDOWS_EXTRA})
+ ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(umskt _umskt ${OPENSSL_CRYPTO_LIBRARIES} ${ZLIB_LIBRARIES} fmt nlohmann_json::nlohmann_json umskt::rc ${UMSKT_LINK_LIBS})
TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS})
- IF(MSVC AND MSVC_MSDOS_STUB)
+ IF (MSVC AND MSVC_MSDOS_STUB)
SET_PROPERTY(TARGET umskt APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB})
- ENDIF()
+ ENDIF ()
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- install(TARGETS umskt DESTINATION bin)
- ENDIF()
+ INSTALL(TARGETS umskt DESTINATION bin)
+ ENDIF ()
### Copy Shared Libraries and dependency files
IF (OPENSSL_CRYPTO_SHARED)
GET_FILENAME_COMPONENT(OPENSSL_CRYPTO_LIBRARY_FILENAME ${OPENSSL_CRYPTO_LIBRARY} NAME)
CONFIGURE_FILE(${OPENSSL_CRYPTO_LIBRARY} "${CMAKE_CURRENT_BINARY_DIR}/${OPENSSL_CRYPTO_LIBRARY_FILENAME}" COPYONLY)
- ENDIF()
-ENDIF()
+ ENDIF ()
+ENDIF ()
diff --git a/Dockerfile b/Dockerfile
index 81cea46..58daeb1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/Dockerfile.djgpp b/Dockerfile.djgpp
index 4f0784a..a718689 100644
--- a/Dockerfile.djgpp
+++ b/Dockerfile.djgpp
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/Dockerfile.emscripten b/Dockerfile.emscripten
index e7e6bad..af3fcee 100644
--- a/Dockerfile.emscripten
+++ b/Dockerfile.emscripten
@@ -1,6 +1,6 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/Dockerfile.windows b/Dockerfile.windows
index 30711aa..5c23d1c 100644
--- a/Dockerfile.windows
+++ b/Dockerfile.windows
@@ -2,7 +2,7 @@
# This file is a part of the UMSKT Project
#
-# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+# Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
diff --git a/keys.json b/keys.json
index f5a144b..873ae55 100644
--- a/keys.json
+++ b/keys.json
@@ -1,154 +1,750 @@
{
"Products": {
- "Windows CE Platform Builder 3": {
- "BINK": ["00", "01", "0E", "0D", "0F"]
+ "WINCEPB3": {
+ "Name": "Windows CE Platform Builder 3",
+ "BINK": [
+ "00",
+ "01",
+ "0E",
+ "0D",
+ "0F"
+ ]
},
- "Windows CE .Net Platform Builder 4": {
- "BINK": ["00", "01"]
+ "WINCEPB4": {
+ "Name": "Windows CE .Net Platform Builder 4",
+ "BINK": [
+ "00",
+ "01"
+ ]
},
- "Windows 98 (all)": {
- "BINK": ["02","03"]
+ "WIN98": {
+ "Name": "Windows 98 (all types)",
+ "BINK": [
+ "02",
+ "03"
+ ]
},
- "Office 2000": {
- "BINK": ["04", "05"]
+ "OFFICE2K": {
+ "Name": "Office 2000 (all variants)",
+ "BINK": [
+ "04",
+ "05"
+ ]
},
- "Internet Security and Acceleration (ISA) Server 2004": {
- "BINK": ["06", "07"]
+ "ISA2K4": {
+ "Name": "Internet Security and Acceleration (ISA) Server 2004",
+ "BINK": [
+ "06",
+ "07"
+ ]
},
- "PLUS! for Windows XP": {
- "BINK": ["08", "09"]
+ "PLUSXP": {
+ "Name": "PLUS! for Windows XP",
+ "BINK": [
+ "08",
+ "09"
+ ]
},
- "Windows 2000 Server (all)": {
- "BINK": ["0A", "13"]
+ "WIN2KSVR": {
+ "Name": "Windows 2000 Server (all types)",
+ "BINK": [
+ "0A",
+ "13"
+ ]
},
- "Office Communicator 2007": {
- "BINK": ["0C", "0D"]
+ "OFFICEC2007": {
+ "Name": "Office Communicator 2007",
+ "BINK": [
+ "0C",
+ "0D"
+ ]
},
- "Windows Embedded POSReady 2009": {
- "BINK": ["0D", "0D"]
+ "POS2009": {
+ "Name": "Windows Embedded POSReady 2009",
+ "BINK": [
+ "0D",
+ "0D"
+ ],
+ "DPC": {
+ "0D": [
+ {
+ "Min": 100,
+ "Max": 199,
+ "IsEvaluation": true,
+ "EvaluationDays": 125
+ },
+ {
+ "Min": 200,
+ "Max": 619,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 940,
+ "Max": 960,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 963,
+ "Max": 979,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 985,
+ "Max": 986,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 996,
+ "Max": 996,
+ "IsEvaluation": true,
+ "EvaluationDays": 125
+ },
+ {
+ "Min": 997,
+ "Max": 997,
+ "IsEvaluation": true,
+ "EvaluationDays": 370
+ },
+ {
+ "Min": 998,
+ "Max": 998,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 620,
+ "Max": 620,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 621,
+ "Max": 621,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 622,
+ "Max": 622,
+ "IsEvaluation": true,
+ "EvaluationDays": 125
+ },
+ {
+ "Min": 623,
+ "Max": 623,
+ "IsEvaluation": true,
+ "EvaluationDays": 370
+ }
+ ]
+ }
},
- "Windows CE .Net Platform Builder 5": {
- "BINK": ["0D", "0D"]
+ "WINCDPB5": {
+ "Name": "Windows CE .Net Platform Builder 5",
+ "BINK": [
+ "0D",
+ "0D"
+ ]
},
- "Commerce Server 2002": {
- "BINK": ["0E", "0F"]
+ "CSERV2K2": {
+ "Name": "Commerce Server 2002",
+ "BINK": [
+ "0E",
+ "0F"
+ ]
},
- "Windows 2000 Professional": {
- "BINK": ["12", "13"]
+ "WIN2K": {
+ "Name": "Windows 2000 Professional",
+ "BINK": [
+ "12",
+ "13"
+ ]
},
- "Office for Mac 2004 / 2008": {
- "BINK": ["18", "19"]
+ "OFFICEMAC2KX": {
+ "Name": "Office for Mac 2004 / 2008",
+ "BINK": [
+ "18",
+ "19"
+ ]
},
- "Windows ME": {
- "BINK": ["1C", "1D"]
+ "WINME": {
+ "Name": "Windows ME",
+ "BINK": [
+ "1C",
+ "1D"
+ ]
},
- "Office XP Applications": {
- "BINK": ["20", "21"]
+ "OFFICEXPA": {
+ "Name": "Office XP Applications",
+ "BINK": [
+ "20",
+ "21"
+ ]
},
- "Works Suite 2003 and 2004": {
- "BINK": ["20", "21"]
+ "WORKS2K3X": {
+ "Name": "Works Suite 2003 and 2004",
+ "BINK": [
+ "20",
+ "21"
+ ]
},
- "Office XP": {
- "BINK": ["22", "23"]
+ "OFFICEXP": {
+ "Name": "Office XP",
+ "BINK": [
+ "22",
+ "23"
+ ],
+ "Activation": "OFFICEXP"
},
- "Visual Studio .Net / .Net 2003": {
- "BINK": ["24", "25"]
+ "VSNET2KX": {
+ "Name": "Visual Studio .Net / .Net 2003",
+ "BINK": [
+ "24",
+ "25"
+ ]
},
- "Windows XP Professional Evaluation": {
- "BINK": ["28", "29"]
+ "WINXPPEVAL": {
+ "Name": "Windows XP Professional Evaluation",
+ "BINK": [
+ "28",
+ "29"
+ ],
+ "Activation": "WINXP"
},
- "Windows XP Home": {
- "BINK": ["2A", "2B"]
+ "WINXPH": {
+ "Name": "Windows XP Home",
+ "BINK": [
+ "2A",
+ "2B"
+ ],
+ "DPC": {
+ "2A": [
+ {
+ "Min": 5,
+ "Max": 85,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 337,
+ "Max": 359,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "60"
+ },
+ {
+ "Min": 755,
+ "Max": 779,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 106,
+ "Max": 106,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 187,
+ "Max": 187,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "60"
+ },
+ {
+ "Min": 188,
+ "Max": 188,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "60"
+ },
+ {
+ "Min": 362,
+ "Max": 376,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 377,
+ "Max": 377,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 984,
+ "Max": 984,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ }
+ ],
+ "2B": [
+ {
+ "Min": 119,
+ "Max": 119,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 120,
+ "Max": 169,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 400,
+ "Max": 665,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 667,
+ "Max": 699,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 700,
+ "Max": 754,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 85,
+ "Max": 85,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 86,
+ "Max": 95,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 96,
+ "Max": 105,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 170,
+ "Max": 186,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 189,
+ "Max": 189,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 190,
+ "Max": 190,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 191,
+ "Max": 191,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 107,
+ "Max": 118,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 192,
+ "Max": 336,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 755,
+ "Max": 899,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 921,
+ "Max": 979,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ }
+ ]
+ },
+ "Activation": "WINXP"
},
- "Windows XP Pro": {
- "BINK": ["2C", "2D"]
+ "WINXPP": {
+ "Name": "Windows XP Pro",
+ "BINK": [
+ "2C",
+ "2D"
+ ],
+ "Activation": "WINXP"
},
- "Windows XP Pro IA-64": {
- "BINK": ["2C", "2D"]
+ "WINXPPIA64": {
+ "Name": "Windows XP Pro IA-64",
+ "BINK": [
+ "2C",
+ "2D"
+ ]
},
- "Windows XP Pro VLK": {
- "BINK": ["2E", "2F"]
+ "WINXPPVLK": {
+ "Name": "Windows XP Pro VLK",
+ "BINK": [
+ "2E",
+ "2F"
+ ],
+ "DPC": {
+ "2E": [
+ {
+ "Min": 640,
+ "Max": 699,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 700,
+ "Max": 701,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 704,
+ "Max": 705,
+ "IsEvaluation": false
+ }
+ ]
+ },
+ "Exclusions": [
+ "640200176",
+ "640000035"
+ ]
},
- "Windows XP Fundamentals for Legacy PCs": {
- "BINK": ["2E", "2F"]
+ "WINXPFLPC": {
+ "Name": "Windows XP Fundamentals for Legacy PCs",
+ "BINK": [
+ "2E",
+ "2F"
+ ],
+ "Activation": "WINXP"
},
- "Windows XP Professional K": {
- "BINK": ["30", "31"]
+ "WINXPK": {
+ "Name": "Windows XP Professional K",
+ "BINK": [
+ "30",
+ "31"
+ ],
+ "Activation": "WINXP"
},
- "Windows XP Starter Edition": {
- "BINK": ["32", "33"]
+ "WINXPSE": {
+ "Name": "Windows XP Starter Edition",
+ "BINK": [
+ "32",
+ "33"
+ ],
+ "Activation": "WINXP"
},
- "Windows Longhorn (6.0.3683.0 -> 6.0.4029.0)": {
- "BINK": ["40", "41"]
+ "WINLH4029": {
+ "Name": "Windows Longhorn (6.0.3683.0 -> 6.0.4029.0)",
+ "BINK": [
+ "40",
+ "41"
+ ]
},
- "Halo: Combat Evolved": {
- "BINK": ["50", "51"]
+ "HALOCE": {
+ "Name": "Halo: Combat Evolved/Custom Edition",
+ "BINK": [
+ "50",
+ "51"
+ ]
},
- "Halo: Custom Edition": {
- "BINK": ["50", "51"]
+ "VS2K5": {
+ "Name": "Visual Studio 2005",
+ "BINK": [
+ "52",
+ "53"
+ ]
},
- "Visual Studio 2005": {
- "BINK": ["52", "53"]
+ "WINXPDME": {
+ "Name": "Plus! Digital Media Edition for Windows XP",
+ "BINK": [
+ "52",
+ "53"
+ ],
+ "Activation": "PLUSDME"
},
- "Plus! Digital Media Edition for Windows XP": {
- "BINK": ["52", "53"]
+ "RONROL": {
+ "Name": "Rise of Nations - Rise of Legends",
+ "BINK": [
+ "52",
+ "53"
+ ]
},
- "Rise of Nations - Rise of Legends": {
- "BINK": ["52", "53"]
+ "WINLH4033": {
+ "Name": "Windows Longhorn (6.0.4033.0)",
+ "BINK": [
+ "54",
+ "55"
+ ]
},
- "Windows Longhorn (6.0.4033.0)": {
- "BINK": ["54", "55"]
+ "WINSVR2K3": {
+ "Name": "Windows Server 2003",
+ "BINK": [
+ "54",
+ "55",
+ "58",
+ "59"
+ ],
+ "Activation": "WINSVR2K3",
+ "DPC": {
+ "54": [
+ {
+ "Min": 5,
+ "Max": 84,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 337,
+ "Max": 369,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "60"
+ },
+ {
+ "Min": 755,
+ "Max": 780,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 781,
+ "Max": 789,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ }
+ ],
+ "55": [
+ {
+ "Min": 119,
+ "Max": 119,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 120,
+ "Max": 169,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 170,
+ "Max": 269,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 400,
+ "Max": 699,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 700,
+ "Max": 754,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ }
+ ]
+ }
},
- "Windows Server 2003": {
- "BINK": ["54", "55", "58", "59"]
+ "WINSVR2K3VLK": {
+ "Name": "Windows Server 2003 VLK",
+ "BINK": [
+ "5A",
+ "5B"
+ ],
+ "DPC": {
+ "5A": [
+ {
+ "Min": 640,
+ "Max": 642,
+ "IsEvaluation": false
+ }
+ ]
+ },
+ "Exclusions": [
+ "640200176",
+ "640000035"
+ ]
},
- "Windows Server 2003 VLK": {
- "BINK": ["5A", "5B"]
+ "WINXPP64BVLK": {
+ "Name": "Windows XP Pro 64 Bit Edition VLK",
+ "BINK": [
+ "64",
+ "65"
+ ],
+ "DPC": {
+ "64": [
+ {
+ "Min": 1,
+ "Max": 2,
+ "IsEvaluation": true,
+ "ActivationGraceDays": "14"
+ },
+ {
+ "Min": 640,
+ "Max": 649,
+ "IsEvaluation": false
+ },
+ {
+ "Min": 652,
+ "Max": 657,
+ "IsEvaluation": false
+ }
+ ],
+ "Exclusions": [
+ "640200176",
+ "640000035"
+ ]
+ }
},
- "Windows XP Pro 64 Bit Edition VLK": {
- "BINK": ["64", "65"]
+ "WINXPP64B": {
+ "Name": "Windows XP Pro 64 Bit Edition",
+ "BINK": [
+ "66",
+ "67"
+ ],
+ "DPC": {
+ "66": [
+ {
+ "Min": 306,
+ "Max": 370,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 371,
+ "Max": 410,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "60"
+ }
+ ],
+ "67": [
+ {
+ "Min": 5,
+ "Max": 118,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ },
+ {
+ "Min": 119,
+ "Max": 119,
+ "IsEvaluation": false,
+ "ActivationGraceDays": "30"
+ }
+ ]
+ },
+ "Activation": "WINXP"
},
- "Windows XP Pro 64 Bit Edition": {
- "BINK": ["66", "67"]
+ "WINSVR2K364B": {
+ "Name": "Windows Server 2003 64 Bit",
+ "BINK": [
+ "68",
+ "69",
+ "6C",
+ "6D"
+ ],
+ "Activation": "WINSVR2K3"
},
- "Windows Server 2003 64 Bit": {
- "BINK": ["68", "69", "6C", "6D"]
+ "WINSVR2K3BVLK": {
+ "Name": "Windows Server 2003 64 Bit VLK",
+ "BINK": [
+ "68",
+ "69",
+ "6C",
+ "6D"
+ ]
},
- "Windows Server 2003 64 Bit VLK": {
- "BINK": ["68", "69", "6C", "6D"]
+ "OFFICE2K3A": {
+ "Name": "Office 2003 Applications",
+ "BINK": [
+ "6E",
+ "6F"
+ ],
+ "Activation": "OFFICE2K3"
},
- "Office 2003 Applications": {
- "BINK": ["6E", "6F"]
+ "OFFICE2K3SB": {
+ "Name": "Office 2003 Small Business",
+ "BINK": [
+ "70",
+ "71"
+ ],
+ "Activation": "OFFICE2K3"
},
- "Office 2003 Small Business": {
- "BINK": ["70", "71"]
+ "OFFICE2K3ST": {
+ "Name": "Office 2003 Student and Teacher",
+ "BINK": [
+ "70",
+ "71"
+ ],
+ "Activation": "OFFICE2K3"
},
- "Office 2003 Student and Teacher": {
- "BINK": ["70", "71"]
+ "OFFICE2K3PRO": {
+ "Name": "Office 2003 Professional",
+ "BINK": [
+ "72",
+ "73"
+ ],
+ "Activation": "OFFICE2K3"
},
- "Office 2003 Professional": {
- "BINK": ["72", "73"]
+ "WINLHPREPX": {
+ "Name": "Windows Longhorn (6.0.4039.0 -> Pre PIDGENX)",
+ "BINK": [
+ "74",
+ "75"
+ ]
},
- "Windows Longhorn (6.0.4039.0 -> Pre PIDGENX)": {
- "BINK": ["74", "75"]
+ "ILM2K7": {
+ "Name": "Identity Lifecycle Manager 2007",
+ "BINK": [
+ "78",
+ "79"
+ ]
},
- "Identity Lifecycle Manager 2007": {
- "BINK": ["78", "79"]
+ "VS2K8": {
+ "Name": "Visual Studio 2008",
+ "BINK": [
+ "78",
+ "79"
+ ]
},
- "Visual Studio 2008": {
- "BINK": ["78", "79"]
+ "OFFICE2K7A": {
+ "Name": "Office 2007 Applications",
+ "BINK": [
+ "7E",
+ "7F"
+ ],
+ "Activation": "OFFICE2K7"
},
- "Office 2007 Applications": {
- "BINK": ["7E", "7F"]
+ "OFFICE2K7SB": {
+ "Name": "Office 2007 Basic / Small Business",
+ "BINK": [
+ "80",
+ "81"
+ ],
+ "Activation": "OFFICE2K7"
},
- "Office 2007 Basic / Small Business": {
- "BINK": ["80", "81"]
+ "OFFICE2K7": {
+ "Name": "Office 2007 Standard / Professional / Ultimate / Enterprise",
+ "BINK": [
+ "82",
+ "83"
+ ],
+ "Activation": "OFFICE2K7"
},
- "Office 2007 Standard / Professional / Ultimate / Enterprise": {
- "BINK": ["82", "83"]
- },
- "Office 2007 Home & Student": {
- "BINK": ["88", "89"]
+ "OFFICE2K7HS": {
+ "Name": "Office 2007 Home & Student",
+ "BINK": [
+ "88",
+ "89"
+ ],
+ "Activation": "OFFICE2K7"
}
},
"BINK": {
@@ -1534,7 +2130,8 @@
}
},
"Activation": {
- "Windows XP": {
+ "WINXP": {
+ "Name": "Windows XP",
"flags": {
"XPBrand": true,
"Office": false,
@@ -1549,22 +2146,55 @@
"4": "90078616228674308",
"5": "1"
},
- "mul": "65537",
"priv": "1315384396487572637498562978064321",
"iid_key": "6AC85ED4",
"non_residue": "43",
- "mod_constants": {
- "0": "0x604FA6A1C6346A87",
- "1": "0x2D351C6D04F8B",
- "2": "0x604FA6A1C6346A87",
- "3": "0x2D351C6D04F8B"
- },
- "verification": {
- "low": "351874082296375233",
- "hi": "71307131016268"
- }
+ "quotient": "14670661154467966223547127731350151"
},
- "Whistler": {
+ "WINSVR2K3": {
+ "Name": "Windows Server 2003",
+ "flags": {
+ "XPBrand": true,
+ "Office": false,
+ "version": 0
+ },
+ "p": "102011604035381881",
+ "x": {
+ "0": "0",
+ "1": "9433814980383617",
+ "2": "19168316694801104",
+ "3": "90078616228674308",
+ "4": "90078616228674308",
+ "5": "1"
+ },
+ "priv": "1315384396487572637498562978064321",
+ "iid_key": "6AC85ED4",
+ "non_residue": "43",
+ "quotient": "14670661154467966223547127731350151"
+ },
+ "WINLH": {
+ "Name": "Windows Longhorn - (pre-reset)",
+ "flags": {
+ "XPBrand": true,
+ "Office": false,
+ "version": 0
+ },
+ "p": "102011604035381881",
+ "x": {
+ "0": "0",
+ "1": "9433814980383617",
+ "2": "19168316694801104",
+ "3": "90078616228674308",
+ "4": "90078616228674308",
+ "5": "1"
+ },
+ "priv": "1315384396487572637498562978064321",
+ "iid_key": "6AC85ED4",
+ "non_residue": "43",
+ "quotient": "14670661154467966223547127731350151"
+ },
+ "WINWH": {
+ "Name": "Windows Whistler",
"flags": {
"XPBrand": false,
"Office": false,
@@ -1579,22 +2209,13 @@
"4": "57597400967455908",
"5": "1"
},
- "mul": "",
- "priv": "",
+ "priv": "4420101814959421052277784766820305",
"iid_key": "6AC85ED4",
"non_residue": "2",
- "mod_constants": {
- "0": "",
- "1": "",
- "2": "",
- "3": ""
- },
- "verification": {
- "low": "",
- "hi": ""
- }
+ "quotient": "14613149284703660878250367809118961"
},
- "Office XP": {
+ "OFFICEXP": {
+ "Name": "Office XP",
"flags": {
"XPBrand": true,
"Office": true,
@@ -1609,22 +2230,13 @@
"4": "64728167274549202",
"5": "1"
},
- "mul": "65537",
"priv": "10294349293510589382098112327865153",
"iid_key": "5A30B9F3",
"non_residue": "3",
- "mod_constants": {
- "0": "0x4FA8E4A40CDAE44A",
- "1": "0x2CBAF12A59BBE",
- "2": "0x4FA8E4A40CDAE44A",
- "3": "0x2CBAF12A59BBE"
- },
- "verification": {
- "low": "17284868327322833729",
- "hi": "558057793417439"
- }
+ "quotient": "14515793565989355059134123881456714"
},
- "Office 2003": {
+ "OFFICE2K3": {
+ "Name": "Office 2003",
"flags": {
"XPBrand": false,
"Office": true,
@@ -1639,22 +2251,13 @@
"4": "64728167274549202",
"5": "1"
},
- "mul": "65537",
"priv": "10294349293510589382098112327865153",
"iid_key": "5A30B9F3",
"non_residue": "3",
- "mod_constants": {
- "0": "0x4FA8E4A40CDAE44A",
- "1": "0x2CBAF12A59BBE",
- "2": "0x4FA8E4A40CDAE44A",
- "3": "0x2CBAF12A59BBE"
- },
- "verification": {
- "low": "17284868327322833729",
- "hi": "558057793417439"
- }
+ "quotient": "14515793565989355059134123881456714"
},
- "Office 2007": {
+ "OFFICE2K7": {
+ "Name": "Office 2007",
"flags": {
"XPBrand": false,
"Office": true,
@@ -1669,22 +2272,13 @@
"4": "64728167274549202",
"5": "1"
},
- "mul": "65537",
"priv": "10294349293510589382098112327865153",
"iid_key": "5A30B9F3",
"non_residue": "3",
- "mod_constants": {
- "0": "0x4FA8E4A40CDAE44A",
- "1": "0x2CBAF12A59BBE",
- "2": "0x4FA8E4A40CDAE44A",
- "3": "0x2CBAF12A59BBE"
- },
- "verification": {
- "low": "17284868327322833729",
- "hi": "558057793417439"
- }
+ "quotient": "14515793565989355059134123881456714"
},
- "Plus! Digital Media Edition for Windows XP": {
+ "PLUSDME": {
+ "Name": "Plus! Digital Media Edition for Windows XP",
"flags": {
"XPBrand": true,
"Office": false,
@@ -1699,20 +2293,10 @@
"4": "6252462837094107",
"5": "1"
},
- "mul": "65537",
"priv": "2752030625102368166730185283969067",
"iid_key": "6AC85ED4",
"non_residue": "2",
- "mod_constants": {
- "0": "0x2C5C4D3654A594F0",
- "1": "0x2D36C691A4EA5",
- "2": "0x2C5C4D3654A594F0",
- "3": "0x2D36C691A4EA5"
- },
- "verification": {
- "low": "8953812210935468417",
- "hi": "499255905936912"
- }
+ "quotient": "14672771312721192311137265743402224"
}
}
}
diff --git a/src/cli.cpp b/src/cli.cpp
index 2d4976d..16a2719 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -22,16 +22,39 @@
#include "cli.h"
-CLI::~CLI()
+// define static storage
+Options CLI::options;
+json CLI::keys;
+
+BYTE CLI::Init(int argcIn, char **argvIn)
{
- EC_GROUP_free(eCurve);
- EC_POINT_free(genPoint);
- EC_POINT_free(pubPoint);
- BN_free(privateKey);
- BN_free(genOrder);
+ // set default options
+ options = {argcIn, argvIn, "2E", "", "", "", "", "", "WINXPPVLK", 0,
+ 0, 1, false, false, false, false, false, false, false, STATE_BINK1998_GENERATE};
+
+ SetHelpText();
+
+ BOOL success = parseCommandLine();
+ if (!success)
+ {
+ return options.error;
+ }
+
+ success = processOptions();
+ if (!success)
+ {
+ return 2;
+ }
+
+ return 0;
}
-bool CLI::loadJSON(const fs::path &filename, json *output)
+/**
+ *
+ * @param filename
+ * @return success
+ */
+BOOL CLI::loadJSON(const fs::path &filename)
{
if (!filename.empty() && !fs::exists(filename))
{
@@ -41,16 +64,23 @@ bool CLI::loadJSON(const fs::path &filename, json *output)
else if (fs::exists(filename))
{
std::ifstream f(filename);
- *output = json::parse(f, nullptr, false, false);
+ try
+ {
+ keys = json::parse(f, nullptr, false, false);
+ }
+ catch (const json::exception &e)
+ {
+ fmt::print("ERROR: Exception thrown while parsing {}: {}\n", filename.string(), e.what());
+ }
}
else if (filename.empty())
{
cmrc::embedded_filesystem fs = cmrc::umskt::get_filesystem();
- cmrc::file keys = fs.open("keys.json");
- *output = json::parse(keys, nullptr, false, false);
+ cmrc::file jsonFile = fs.open("keys.json");
+ keys = json::parse(jsonFile, nullptr, false, false);
}
- if (output->is_discarded())
+ if (keys.is_discarded())
{
fmt::print("ERROR: Unable to parse keys from {}\n", filename.string());
return false;
@@ -59,314 +89,80 @@ bool CLI::loadJSON(const fs::path &filename, json *output)
return true;
}
-void CLI::showHelp(char *argv[])
+/**
+ *
+ * @return success
+ */
+BOOL CLI::processOptions()
{
- fmt::print("usage: {} \n", argv[0]);
- fmt::print("\t-h --help\tshow this message\n");
- fmt::print("\t-v --verbose\tenable verbose output\n");
- fmt::print("\t-n --number\tnumber of keys to generate (defaults to 1)\n");
- fmt::print("\t-f --file\tspecify which keys file to load\n");
- fmt::print("\t-i --instid\tinstallation ID used to generate confirmation ID\n");
- fmt::print("\t-m --mode\tproduct family to activate.\n\t\t\tvalid options are \"WINDOWS\", \"OFFICEXP\", "
- "\"OFFICE2K3\", \"OFFICE2K7\" or \"PLUSDME\"\n\t\t\t(defaults to \"WINDOWS\")\n");
- fmt::print("\t-p --productid\tthe product ID of the Program to activate. only required for Office 2K3 and Office "
- "2K7 programs\n");
- fmt::print("\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n");
- fmt::print("\t-l --list\tshow which products/binks can be loaded\n");
- fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n");
- fmt::print("\t-s --serial\tspecifies a serial to use in the product ID (defaults to random, BINK1998 only)\n");
- fmt::print("\t-u --upgrade\tspecifies the Product Key will be an \"Upgrade\" version\n");
- fmt::print("\t-V --validate\tproduct key to validate signature\n");
- fmt::print("\t-N --nonewlines\tdisables newlines (for easier embedding in other apps)\n");
- fmt::print("\n");
-}
-
-int CLI::parseCommandLine(int argc, char *argv[], Options *options)
-{
- // set default options
- *options = Options{"2E", "", "", "", "", 640, 0, 1,
- false, false, false, false, false, false, false, MODE_BINK1998_GENERATE,
- WINDOWS};
-
- for (int i = 1; i < argc; i++)
+ if (options.verbose)
{
- std::string arg = argv[i];
- if (arg == "-v" || arg == "--verbose")
- {
- options->verbose = true;
- UMSKT::setDebugOutput(stderr);
- }
- else if (arg == "-h" || arg == "--help")
- {
- options->help = true;
- }
- else if (arg == "-n" || arg == "--number")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- int nKeys;
- if (!sscanf(argv[i + 1], "%d", &nKeys))
- {
- options->error = true;
- }
- else
- {
- options->numKeys = nKeys;
- }
- i++;
- }
- else if (arg == "-b" || arg == "--bink")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- options->binkid = argv[i + 1];
- i++;
- }
- else if (arg == "-l" || arg == "--list")
- {
- options->list = true;
- }
- else if (arg == "-c" || arg == "--channelid")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- int siteID;
- if (!sscanf(argv[i + 1], "%d", &siteID))
- {
- options->error = true;
- }
- else
- {
- options->channelID = siteID;
- }
- i++;
- }
- else if (arg == "-s" || arg == "--serial")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- int serial_val;
- if (!sscanf(argv[i + 1], "%d", &serial_val))
- {
- options->error = true;
- }
- else
- {
- options->serialSet = true;
- options->serial = serial_val;
- }
- i++;
- }
- else if (arg == "-u" || arg == "--upgrade")
- {
- options->upgrade = true;
- }
- else if (arg == "-f" || arg == "--file")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- options->keysFilename = argv[i + 1];
- i++;
- }
- else if (arg == "-i" || arg == "--instid")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- options->instid = argv[i + 1];
- options->applicationMode = MODE_CONFIRMATION_ID;
- i++;
- }
- else if (arg == "-m" || arg == "--mode")
- {
- std::string mode = argv[i + 1];
- char *p = &mode[0];
- for (; *p; p++)
- {
- *p = toupper((unsigned char)*p);
- }
- p = &mode[0];
- if (strcmp(p, "WINDOWS") == 0)
- {
- options->activationMode = WINDOWS;
- }
- else if (strcmp(p, "OFFICEXP") == 0)
- {
- options->activationMode = OFFICE_XP;
- }
- else if (strcmp(p, "OFFICE2K3") == 0)
- {
- options->activationMode = OFFICE_2K3;
- }
- else if (strcmp(p, "OFFICE2K7") == 0)
- {
- options->activationMode = OFFICE_2K7;
- }
- else if (strcmp(p, "PLUSDME") == 0)
- {
- options->activationMode = PLUS_DME;
- }
- i++;
- }
- else if (arg == "-p" || arg == "--productid")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
- options->productid = argv[i + 1];
- i++;
- }
- else if (arg == "-V" || arg == "--validate")
- {
- if (i == argc - 1)
- {
- options->error = true;
- break;
- }
-
- options->keyToCheck = argv[i + 1];
- options->applicationMode = MODE_BINK1998_VALIDATE;
- i++;
- }
- else if (arg == "-N" || arg == "--nonewlines")
- {
- options->nonewlines = true;
- }
- else
- {
- options->error = true;
- }
- }
-
- // make sure that a product id is entered for OFFICE_2K3 or OFFICE_2K7 IIDs
- if ((options->activationMode == OFFICE_2K3 || options->activationMode == OFFICE_2K7) &&
- (options->productid.empty() || options->instid.empty()))
- {
- return options->error = true;
- }
-
- return !options->error;
-}
-
-int CLI::validateCommandLine(Options *options, char *argv[], json *keys)
-{
- if (options->help || options->error)
- {
- if (options->error)
- {
- fmt::print("error parsing command line options\n");
- }
- showHelp(argv);
- return 1;
- }
-
- if (options->verbose)
- {
- if (options->keysFilename.empty())
+ if (options.keysFilename.empty())
{
fmt::print("Loading internal keys file\n");
}
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))
{
- return 2;
+ options.error = true;
+ return false;
}
- if (options->verbose)
+ if (options.verbose)
{
- if (options->keysFilename.empty())
+ if (options.keysFilename.empty())
{
fmt::print("Loaded internal keys file successfully\n");
}
else
{
- fmt::print("Loaded keys from {} successfully\n", options->keysFilename);
+ 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 &i : keys["Products"].items())
{
+ auto el = i.value();
int id;
- sscanf((el.value()["BINK"][0]).get().c_str(), "%x", &id);
- std::cout << el.key() << ": " << el.value()["BINK"] << std::endl;
+ sscanf(&(el["BINK"][0]).get()[0], "%x", &id);
+ fmt::print("{}\n\tName: {}\n\tBINKs: ", i.key(), el["Name"].get());
+ std::cout << el["BINK"] << std::endl << std::endl;
}
- fmt::print("\n\n");
- fmt::print("** Please note: any BINK ID other than 2E is considered experimental at this time **\n");
fmt::print("\n");
- return 1;
+ return false;
}
- int intBinkID;
- sscanf(options->binkid.c_str(), "%x", &intBinkID);
+ DWORD intBinkID;
+ sscanf(&options.binkid[0], "%x", &intBinkID);
// FE and FF are BINK 1998, but do not generate valid keys, so we throw an error
if (intBinkID >= 0xFE)
{
fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n");
- return 1;
+ return false;
}
if (intBinkID >= 0x40)
{
// set bink2002 validate mode if in bink1998 validate mode, else set bink2002 generate mode
- options->applicationMode =
- (options->applicationMode == MODE_BINK1998_VALIDATE) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE;
+ options.state = (options.state == STATE_BINK1998_VALIDATE) ? STATE_BINK2002_VALIDATE : STATE_BINK2002_GENERATE;
}
- if (options->channelID > 999)
- {
- fmt::print("ERROR: refusing to create a key with a Channel ID greater than 999\n");
- return 1;
- }
-
- // don't allow any serial not between 0 and 999999
- if (options->serial > 999999 || options->serial < 0)
- {
- fmt::print("ERROR: refusing to create a key with a Serial not between 000000 and 999999\n");
- return 1;
- }
-
- return 0;
+ return true;
}
void CLI::printID(DWORD *pid)
{
- char raw[12];
- char b[6], c[8];
- int i, digit = 0;
+ char raw[12], b[6], c[8];
+ char i, digit = 0;
// Convert PID to ascii-number (=raw)
snprintf(raw, sizeof(raw), "%09u", pid[0]);
@@ -392,23 +188,33 @@ void CLI::printID(DWORD *pid)
c[6] = digit + '0';
c[7] = 0;
- fmt::print("> Product ID: PPPPP-{}-{}-23xxx\n", b, c);
+ fmt::print("> Product ID: PPPPP-{}-{}-BBxxx\n", b, c);
}
-void CLI::printKey(char *pk)
+/**
+ *
+ * @param pk
+ */
+void CLI::printKey(std::string pk)
{
- assert(strlen(pk) >= PK_LENGTH);
+ assert(pk.length() >= PK_LENGTH);
- std::string spk = pk;
- fmt::print("{}-{}-{}-{}-{}", spk.substr(0, 5), spk.substr(5, 5), spk.substr(10, 5), spk.substr(15, 5),
- spk.substr(20, 5));
+ fmt::print("{}-{}-{}-{}-{}", pk.substr(0, 5), pk.substr(5, 5), pk.substr(10, 5), pk.substr(15, 5),
+ pk.substr(20, 5));
}
-bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH])
+/**
+ *
+ * @param in_key
+ * @param out_key
+ * @return
+ */
+BOOL CLI::stripKey(const std::string &in_key, std::string &out_key)
{
// copy out the product key stripping out extraneous characters
- const char *p = in_key;
- size_t i = 0;
+ const char *p = &in_key[0];
+ BYTE i = 0;
+
for (; *p; p++)
{
// strip out space or dash
@@ -431,283 +237,388 @@ bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH])
}
}
}
+
// only return true if we've handled exactly PK_LENGTH chars
return (i == PK_LENGTH);
}
-CLI::CLI(Options options, json keys)
+/**
+ *
+ * @param pidgen3
+ * @return success
+ */
+BOOL CLI::InitPIDGEN3(PIDGEN3 *pidgen3)
{
- this->options = options;
- this->keys = keys;
+ if (!options.productCode.empty())
+ {
+ const char *productCode = &options.productCode[0];
+ auto product = keys["Products"][productCode];
- this->BINKID = options.binkid.c_str();
+ if (options.verbose)
+ {
+ fmt::print("Selecting product: {}\n", productCode);
+ }
- // We cannot produce a valid key without knowing the private key k. The reason for this is that
- // we need the result of the function K(x; y) = kG(x; y).
- this->privateKey = BN_new();
+ if (options.oem)
+ {
+ options.binkid = product["BINK"][1].get();
+ }
+ else
+ {
+ options.binkid = product["BINK"][0].get();
+ }
- // We can, however, validate any given key using the available public key: {p, a, b, G, K}.
- // genOrder the order of the generator G, a value we have to reverse -> Schoof's Algorithm.
- this->genOrder = BN_new();
+ if (options.verbose)
+ {
+ fmt::print("Selected BINK: {}\n", options.binkid);
+ }
- /* Computed data */
- BN_dec2bn(&this->genOrder, this->keys["BINK"][this->BINKID]["n"].get().c_str());
- BN_dec2bn(&this->privateKey, this->keys["BINK"][this->BINKID]["priv"].get().c_str());
+ std::vector filtered;
+
+ if (product.contains("DPC") && options.channelID == 0)
+ {
+ for (auto const &i : product["DPC"][options.binkid].items())
+ {
+ auto el = i.value();
+ if (!el["IsEvaluation"].get())
+ {
+ filtered.push_back(el);
+ }
+ }
+
+ // roll a die to choose which DPC entry to pick
+ auto rand = UMSKT::getRandom();
+ auto dpc = filtered[rand % filtered.size()];
+ auto min = dpc["Min"].get(), max = dpc["Max"].get();
+ options.channelID = min + (rand % (max - min));
+ if (options.verbose)
+ {
+ fmt::print("Selected channel ID: {} (DPC entry {})\n", options.channelID, rand % filtered.size());
+ }
+ }
+
+ return false;
+ }
+
+ const char *BINKID = &options.binkid[0];
+ auto bink = keys["BINK"][BINKID];
if (options.verbose)
{
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", BINKID);
fmt::print("----------------------------------------------------------- \n");
- fmt::print(" P: {}\n", this->keys["BINK"][this->BINKID]["p"].get());
- fmt::print(" a: {}\n", this->keys["BINK"][this->BINKID]["a"].get());
- fmt::print(" b: {}\n", this->keys["BINK"][this->BINKID]["b"].get());
- fmt::print("Gx: {}\n", this->keys["BINK"][this->BINKID]["g"]["x"].get());
- fmt::print("Gy: {}\n", this->keys["BINK"][this->BINKID]["g"]["y"].get());
- fmt::print("Kx: {}\n", this->keys["BINK"][this->BINKID]["pub"]["x"].get());
- fmt::print("Ky: {}\n", this->keys["BINK"][this->BINKID]["pub"]["y"].get());
- fmt::print(" n: {}\n", this->keys["BINK"][this->BINKID]["n"].get());
- fmt::print(" k: {}\n", this->keys["BINK"][this->BINKID]["priv"].get());
+ fmt::print(" P: {}\n", bink["p"].get());
+ fmt::print(" a: {}\n", bink["a"].get());
+ fmt::print(" b: {}\n", bink["b"].get());
+ fmt::print("Gx: {}\n", bink["g"]["x"].get());
+ fmt::print("Gy: {}\n", bink["g"]["y"].get());
+ fmt::print("Kx: {}\n", bink["pub"]["x"].get());
+ fmt::print("Ky: {}\n", bink["pub"]["y"].get());
+ fmt::print(" n: {}\n", bink["n"].get());
+ fmt::print(" k: {}\n", bink["priv"].get());
fmt::print("\n");
}
- eCurve = PIDGEN3::initializeEllipticCurve(this->keys["BINK"][this->BINKID]["p"].get(),
- this->keys["BINK"][this->BINKID]["a"].get(),
- this->keys["BINK"][this->BINKID]["b"].get(),
- this->keys["BINK"][this->BINKID]["g"]["x"].get(),
- this->keys["BINK"][this->BINKID]["g"]["y"].get(),
- this->keys["BINK"][this->BINKID]["pub"]["x"].get(),
- this->keys["BINK"][this->BINKID]["pub"]["y"].get(),
- this->genPoint, this->pubPoint);
+ pidgen3->LoadEllipticCurve(bink["p"].get(), bink["a"].get(), bink["b"].get(),
+ bink["g"]["x"].get(), bink["g"]["y"].get(),
+ bink["pub"]["x"].get(), bink["pub"]["y"].get(),
+ bink["n"].get(), bink["priv"].get());
- this->count = 0;
- this->total = this->options.numKeys;
+ pidgen3->setChannelID(options.channelID);
+ if (options.verbose)
+ {
+ fmt::print("> Channel ID: {:03d}\n", options.channelID);
+ }
+
+ if (options.serialSet)
+ {
+ pidgen3->setSerial(options.serial);
+ if (options.verbose)
+ {
+ fmt::print("> Serial {:#09d}\n", options.serial);
+ }
+ }
+
+ return true;
}
-int CLI::BINK1998Generate()
+/**
+ *
+ * @param confid
+ * @return success
+ */
+BOOL CLI::InitConfirmationID(ConfirmationID *confid)
{
+ return true;
+}
+
+/**
+ *
+ * @return success
+ */
+BOOL CLI::BINK1998Generate()
+{
+ auto bink1998 = BINK1998();
+ BOOL retval = InitPIDGEN3(&bink1998);
+ if (!retval)
+ {
+ return retval;
+ }
+
// raw PID/serial value
- DWORD nRaw = this->options.channelID * 1'000'000; /* <- change */
+ DWORD nRaw = options.channelID * 1'000'000;
// using user-provided serial
- if (this->options.serialSet)
+ if (options.serialSet)
{
// just in case, make sure it's less than 999999
- int serialRnd = (this->options.serial % 999999);
+ int serialRnd = (options.serial % 999999);
nRaw += serialRnd;
}
else
{
// generate a random number to use as a serial
- BIGNUM *bnrand = BN_new();
- BN_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
-
- int oRaw;
- char *cRaw = BN_bn2dec(bnrand);
-
- sscanf(cRaw, "%d", &oRaw);
+ auto oRaw = UMSKT::getRandom();
nRaw += (oRaw % 999999); // ensure our serial is less than 999999
- BN_free(bnrand);
}
- if (this->options.verbose)
+ if (options.verbose)
{
// print the resulting Product ID
// PID value is printed in BINK1998::Generate
printID(&nRaw);
}
- // generate a key
- BN_sub(this->privateKey, this->genOrder, this->privateKey);
-
- for (int i = 0; i < this->total; i++)
+ for (int i = 0; i < total; i++)
{
- PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw,
- options.upgrade, this->pKey);
+ bink1998.Generate(pKey);
- bool isValid = PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
+ bool isValid = bink1998.Verify(pKey);
if (isValid)
{
- CLI::printKey(this->pKey);
- if (i < this->total - 1 || this->options.verbose)
+ CLI::printKey(pKey);
+ if (i < total - 1 || options.verbose)
{
fmt::print("\n");
}
- this->count += isValid;
+ count += isValid;
}
else
{
- if (this->options.verbose)
+ if (options.verbose)
{
- CLI::printKey(this->pKey);
+ CLI::printKey(pKey);
fmt::print(" [Invalid]");
- if (i < this->total - 1)
+ if (i < total - 1)
{
fmt::print("\n");
}
}
- this->total++; // queue a redo, basically
+ total++; // queue a redo, basically
}
}
- if (this->options.verbose)
+ if (options.verbose)
{
- fmt::print("\nSuccess count: {}/{}", this->count, this->total);
+ fmt::print("\nSuccess count: {}/{}\n", count, total);
}
- if (!options.nonewlines)
- {
- fmt::print("\n");
- }
-
- return 0;
+ return true;
}
-int CLI::BINK2002Generate()
+/**
+ *
+ * @return success
+ */
+BOOL CLI::BINK2002Generate()
{
- DWORD pChannelID = this->options.channelID;
-
- if (this->options.verbose)
- {
- fmt::print("> Channel ID: {:03d}\n", this->options.channelID);
- }
+ auto bink2002 = BINK2002();
+ InitPIDGEN3(&bink2002);
// generate a key
- for (int i = 0; i < this->total; i++)
+ for (int i = 0; i < total; i++)
{
DWORD pAuthInfo;
RAND_bytes((BYTE *)&pAuthInfo, 4);
pAuthInfo &= BITMASK(10);
- if (this->options.verbose)
+ if (options.verbose)
{
fmt::print("> AuthInfo: {}\n", pAuthInfo);
}
- PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID,
- pAuthInfo, options.upgrade, this->pKey);
+ bink2002.Generate(pKey);
- bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
+ bool isValid = bink2002.Verify(pKey);
if (isValid)
{
- CLI::printKey(this->pKey);
- if (i < this->total - 1 || this->options.verbose)
+ CLI::printKey(pKey);
+ if (i < total - 1 || options.verbose)
{ // check if end of list or verbose
fmt::print("\n");
}
- this->count += isValid; // add to count
+ count += isValid; // add to count
}
else
{
- if (this->options.verbose)
+ if (options.verbose)
{
- CLI::printKey(this->pKey); // print the key
- fmt::print(" [Invalid]"); // and add " [Invalid]" to the key
+ CLI::printKey(pKey); // print the key
+ fmt::print(" [Invalid]"); // and add " [Invalid]" to the key
if (i < this->total - 1)
{ // check if end of list
fmt::print("\n");
}
}
- this->total++; // queue a redo, basically
+ total++; // queue a redo, basically
}
}
- if (this->options.verbose)
+ if (options.verbose)
{
- fmt::print("\nSuccess count: {}/{}", this->count, this->total);
+ fmt::print("\nSuccess count: {}/{}\n", count, total);
}
- if (!this->options.nonewlines)
- {
- fmt::print("\n");
- }
-
- return 0;
+ return true;
}
-int CLI::BINK1998Validate()
+/**
+ *
+ * @return success
+ */
+BOOL CLI::BINK1998Validate()
{
- char product_key[PK_LENGTH]{};
+ auto bink1998 = BINK1998();
+ InitPIDGEN3(&bink1998);
- if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key))
+ std::string product_key;
+
+ if (!CLI::stripKey(options.keyToCheck, product_key))
{
fmt::print("ERROR: Product key is in an incorrect format!\n");
- return 1;
+ return false;
}
CLI::printKey(product_key);
fmt::print("\n");
- if (!PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key))
+ if (!bink1998.Verify(product_key))
{
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
- return 1;
+ return false;
}
fmt::print("Key validated successfully!\n");
- return 0;
+ return true;
}
-int CLI::BINK2002Validate()
+/**
+ *
+ * @return success
+ */
+BOOL CLI::BINK2002Validate()
{
- char product_key[PK_LENGTH]{};
+ auto bink2002 = BINK2002();
+ InitPIDGEN3(&bink2002);
- if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key))
+ std::string product_key;
+
+ if (!CLI::stripKey(options.keyToCheck, product_key))
{
fmt::print("ERROR: Product key is in an incorrect format!\n");
- return 1;
+ return false;
}
CLI::printKey(product_key);
fmt::print("\n");
- if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key))
+ if (!bink2002.Verify(product_key))
{
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
- return 1;
+ return false;
}
fmt::print("Key validated successfully!\n");
- return 0;
+ return true;
}
-int CLI::ConfirmationID()
+/**
+ *
+ * @return success
+ */
+BOOL CLI::ConfirmationIDGenerate()
{
- char confirmation_id[49];
+ std::string confirmation_id;
- auto confid = new class ConfirmationID();
- int err = confid->Generate(this->options.instid.c_str(), confirmation_id, options.productid);
+ auto confid = ConfirmationID();
+ int err = confid.Generate(options.instid, confirmation_id, options.productid);
if (err == SUCCESS)
{
- fmt::print(confirmation_id);
- if (!this->options.nonewlines)
- {
- fmt::print("\n");
- }
- return 0;
+ fmt::print("{}\n", confirmation_id);
+ return true;
}
switch (err)
{
case ERR_TOO_SHORT:
fmt::print("ERROR: Installation ID is too short.\n");
+ break;
case ERR_TOO_LARGE:
fmt::print("ERROR: Installation ID is too long.\n");
+ break;
case ERR_INVALID_CHARACTER:
fmt::print("ERROR: Invalid character in installation ID.\n");
+ break;
case ERR_INVALID_CHECK_DIGIT:
fmt::print("ERROR: Installation ID checksum failed. Please check that it is typed correctly.\n");
+ break;
case ERR_UNKNOWN_VERSION:
fmt::print("ERROR: Unknown installation ID version.\n");
+ break;
case ERR_UNLUCKY:
fmt::print("ERROR: Unable to generate valid confirmation ID.\n");
+ break;
default:
fmt::print("Unknown error occurred during Confirmation ID generation: {}\n", err);
+ break;
}
- return 1;
+
+ return false;
+}
+/**
+ *
+ * @return application status code
+ */
+int CLI::Run()
+{
+ BINK1998Generate();
+ /*
+ switch (state)
+ {
+ case STATE_BINK1998_GENERATE:
+ return BINK1998Generate();
+
+ case STATE_BINK2002_GENERATE:
+ return BINK2002Generate();
+
+ case STATE_BINK1998_VALIDATE:
+ return BINK1998Validate();
+
+ case STATE_BINK2002_VALIDATE:
+ return BINK2002Validate();
+
+ case STATE_CONFIRMATION_ID:
+ return ConfirmationIDGenerate();
+
+ default:
+ return 1;
+ }
+ */
+ return 0;
}
diff --git a/src/cli.h b/src/cli.h
index 84ace37..22a8efe 100644
--- a/src/cli.h
+++ b/src/cli.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,16 +16,28 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/6/2023
+ * @FileCreated by Neo on 06/06/2023
* @Maintainer Neo
*/
#ifndef UMSKT_CLI_H
#define UMSKT_CLI_H
-#include "header.h"
+#include "typedefs.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
#include
+#include
+#include
+
+using json = nlohmann::json;
+namespace fs = std::filesystem;
#include "libumskt/confid/confid.h"
#include "libumskt/libumskt.h"
@@ -33,68 +45,100 @@
#include "libumskt/pidgen3/BINK1998.h"
#include "libumskt/pidgen3/BINK2002.h"
#include "libumskt/pidgen3/PIDGEN3.h"
+#include "options.h"
CMRC_DECLARE(umskt);
-enum MODE
+enum APPLICATION_STATE
{
- MODE_BINK1998_GENERATE = 0,
- MODE_BINK2002_GENERATE = 1,
- MODE_CONFIRMATION_ID = 2,
- MODE_BINK1998_VALIDATE = 3,
- MODE_BINK2002_VALIDATE = 4,
+ STATE_BINK1998_GENERATE,
+ STATE_BINK2002_GENERATE,
+ STATE_CONFIRMATION_ID,
+ STATE_BINK1998_VALIDATE,
+ STATE_BINK2002_VALIDATE
};
struct Options
{
+ int argc;
+ char **argv;
+
std::string binkid;
std::string keysFilename;
std::string instid;
std::string keyToCheck;
std::string productid;
- int channelID;
- int serial;
- int numKeys;
- bool upgrade;
- bool serialSet;
- bool verbose;
- bool help;
- bool error;
- bool list;
- bool nonewlines;
+ std::string authInfo;
+ std::string productCode;
- MODE applicationMode;
- ACTIVATION_ALGORITHM activationMode;
+ DWORD channelID;
+ DWORD serial;
+ DWORD numKeys;
+ BOOL oem;
+ BOOL upgrade;
+ BOOL serialSet;
+ BOOL verbose;
+ BOOL help;
+ BOOL error;
+ BOOL list;
+
+ APPLICATION_STATE state;
};
class CLI
{
- Options options;
- json keys;
- const char *BINKID;
- BIGNUM *privateKey, *genOrder;
- EC_POINT *genPoint, *pubPoint;
- EC_GROUP *eCurve;
- char pKey[25];
- int count, total;
+ std::string pKey;
+ DWORD count, total;
+
+ static Options options;
public:
- CLI(Options options, json keys);
- ~CLI();
+ CLI()
+ {
+ count = 0;
+ total = options.numKeys;
+ }
- static bool loadJSON(const fs::path &filename, json *output);
- static void showHelp(char *argv[]);
- static int parseCommandLine(int argc, char *argv[], Options *options);
- static int validateCommandLine(Options *options, char *argv[], json *keys);
+ static std::array helpOptions;
+ static json keys;
+
+ static BYTE Init(int argv, char *argc[]);
+ static void SetHelpText();
+
+ static CLIHandlerFunc loadJSON;
+ static CLIHandlerFunc DisplayHelp;
+ static CLIHandlerFunc DisplayErrorMessage;
+ static CLIHandlerFunc SetVerboseOption;
+ static CLIHandlerFunc SetDebugOption;
+ static CLIHandlerFunc SetListOption;
+ static CLIHandlerFunc SetOEMOption;
+ static CLIHandlerFunc SetUpgradeOption;
+ static CLIHandlerFunc SetFileOption;
+ static CLIHandlerFunc SetNumberOption;
+ static CLIHandlerFunc SetChannelIDOption;
+ static CLIHandlerFunc SetBINKOption;
+ static CLIHandlerFunc SetSerialOption;
+ static CLIHandlerFunc SetActivationIDOption;
+ static CLIHandlerFunc SetProductIDOption;
+ static CLIHandlerFunc SetValidateOption;
+ static CLIHandlerFunc SetProductCodeOption;
+
+ static BOOL parseCommandLine();
+ static BOOL processOptions();
static void printID(DWORD *pid);
- static void printKey(char *pk);
- static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
+ static void printKey(std::string pk);
+ static BOOL stripKey(const std::string &in_key, std::string &out_key);
- int BINK1998Generate();
- int BINK2002Generate();
- int BINK1998Validate();
- int BINK2002Validate();
- int ConfirmationID();
+ BOOL InitPIDGEN3(PIDGEN3 *pidgen3);
+ BOOL InitConfirmationID(ConfirmationID *confid);
+
+ BOOL BINK1998Generate();
+ BOOL BINK2002Generate();
+ BOOL BINK1998Validate();
+ BOOL BINK2002Validate();
+ BOOL ConfirmationIDGenerate();
+
+ int Run();
};
#endif // UMSKT_CLI_H
diff --git a/src/libumskt/confid/confid.cpp b/src/libumskt/confid/confid.cpp
index fbb6b1b..c04ecb5 100644
--- a/src/libumskt/confid/confid.cpp
+++ b/src/libumskt/confid/confid.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -29,74 +29,59 @@
#include "confid.h"
-void ConfirmationID::setMod(QWORD mod)
+BOOL ConfirmationID::LoadHyperellipticCurve(QWORD x0, QWORD x1, QWORD x2, QWORD x3, QWORD x4, QWORD x5, Q_OWORD priv,
+ QWORD modulous, QWORD nonresidue, BOOL isOffice, BOOL isXPBrand,
+ BYTE flagVersion)
{
- MOD = mod;
-}
+ curve[0] = x0;
+ curve[1] = x1;
+ curve[2] = x2;
+ curve[3] = x3;
+ curve[4] = x4;
+ curve[5] = x5;
-void ConfirmationID::setNonResidue(QWORD nonResidue)
-{
- NON_RESIDUE = nonResidue;
-}
+ memcpy(&privateKey, &priv, sizeof(Q_OWORD));
-void ConfirmationID::setPValues(QWORD p0, QWORD p1, QWORD p2, QWORD p3)
-{
- p[0] = p0;
- p[1] = p1;
- p[2] = p2;
- p[3] = p3;
-}
-
-void ConfirmationID::setPValues(QWORD pValues[4])
-{
- memcpy(p, pValues, sizeof(*pValues * 4));
-}
-
-void ConfirmationID::setFValues(QWORD f0, QWORD f1, QWORD f2, QWORD f3, QWORD f4, QWORD f5)
-{
- f[0] = f0;
- f[1] = f1;
- f[2] = f2;
- f[3] = f3;
- f[4] = f4;
- f[5] = f5;
-}
-
-void ConfirmationID::setFValues(QWORD fValues[6])
-{
- memcpy(p, fValues, sizeof(*fValues * 6));
-}
-
-void ConfirmationID::setIsOffice(BOOL isOffice)
-{
+ MOD = modulous;
+ NON_RESIDUE = nonresidue;
this->isOffice = isOffice;
+ this->isXPBrand = isXPBrand;
+ this->flagVersion = flagVersion;
+
+ return true;
}
-void ConfirmationID::setIsXPBrand(BOOL isXpBrand)
+BOOL ConfirmationID::LoadHyperellipticCurve(QWORD *f, Q_OWORD priv, QWORD modulous, QWORD nonresidue, BOOL isOffice,
+ BOOL isXPBrand, BYTE flagVersion)
{
- this->isXPBrand = isXpBrand;
+ memcpy(&curve, f, sizeof(curve));
+ memcpy(&privateKey, &priv, sizeof(Q_OWORD));
+
+ MOD = modulous;
+ NON_RESIDUE = nonresidue;
+ this->isOffice = isOffice;
+ this->isXPBrand = isXPBrand;
+ this->flagVersion = flagVersion;
+
+ return true;
}
-void ConfirmationID::setFlagVersion(unsigned int flagVersion)
+DWORD ConfirmationID::calculateCheckDigit(DWORD pid)
{
- ConfirmationID::flagVersion = flagVersion;
-}
-
-int ConfirmationID::calculateCheckDigit(int pid)
-{
- unsigned int i = 0, j = 0, k = 0;
+ DWORD i = 0, j = 0, k = 0;
for (j = pid; j; i += k)
{
k = j % 10;
j /= 10;
}
+
return ((10 * pid) - (i % 7)) + 7;
}
-void ConfirmationID::decode_iid_new_version(unsigned char *iid, unsigned char *hwid, int *version)
+void ConfirmationID::decode_iid_new_version(BYTE *iid, BYTE *hwid, DWORD *version)
{
QWORD buffer[5];
- for (int i = 0; i < 5; i++)
+ for (BYTE i = 0; i < 5; i++)
{
memcpy(&buffer[i], (iid + (4 * i)), 4);
}
@@ -104,7 +89,7 @@ void ConfirmationID::decode_iid_new_version(unsigned char *iid, unsigned char *h
DWORD v1 = (buffer[3] & 0xFFFFFFF8) | 2;
DWORD v2 = ((buffer[3] & 7) << 29) | (buffer[2] >> 3);
QWORD hardwareIDVal = ((QWORD)v1 << 32) | v2;
- for (int i = 0; i < 8; ++i)
+ for (BYTE i = 0; i < 8; ++i)
{
hwid[i] = (hardwareIDVal >> (8 * i)) & 0xFF;
}
@@ -112,13 +97,13 @@ void ConfirmationID::decode_iid_new_version(unsigned char *iid, unsigned char *h
*version = buffer[0] & 7;
}
-void ConfirmationID::Mix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize)
+void ConfirmationID::Mix(BYTE *buffer, BYTE bufSize, const BYTE *key, BYTE keySize)
{
- unsigned char sha1_input[64], sha1_result[20];
- size_t half = bufSize / 2;
+ BYTE sha1_input[64], sha1_result[20];
+ BYTE half = bufSize / 2;
// assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
- for (int external_counter = 0; external_counter < 4; external_counter++)
+ for (BYTE external_counter = 0; external_counter < 4; external_counter++)
{
memset(sha1_input, 0, sizeof(sha1_input));
@@ -144,12 +129,12 @@ void ConfirmationID::Mix(unsigned char *buffer, size_t bufSize, const unsigned c
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
- for (size_t i = half & ~3; i < half; i++)
+ for (BYTE i = half & ~3; i < half; i++)
{
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
}
- for (size_t i = 0; i < half; i++)
+ for (BYTE i = 0; i < half; i++)
{
unsigned char tmp = buffer[i + half];
buffer[i + half] = buffer[i] ^ sha1_result[i];
@@ -158,14 +143,13 @@ 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(BYTE *buffer, BYTE bufSize, const BYTE key[4], BYTE keySize)
{
- unsigned char sha1_input[64];
- unsigned char sha1_result[20];
- size_t half = bufSize / 2;
+ BYTE sha1_input[64], sha1_result[20];
+ BYTE half = bufSize / 2;
// assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
- for (int external_counter = 0; external_counter < 4; external_counter++)
+ for (BYTE external_counter = 0; external_counter < 4; external_counter++)
{
memset(sha1_input, 0, sizeof(sha1_input));
@@ -189,12 +173,12 @@ void ConfirmationID::Unmix(unsigned char *buffer, size_t bufSize, const unsigned
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
- for (size_t i = half & ~3; i < half; i++)
+ for (BYTE i = half & ~3; i < half; i++)
{
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
}
- for (size_t i = 0; i < half; i++)
+ for (BYTE i = 0; i < half; i++)
{
unsigned char tmp = buffer[i];
buffer[i] = buffer[i + half] ^ sha1_result[i];
@@ -203,20 +187,31 @@ 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)
+/**
+ *
+ * @param installationIDIn
+ * @param confirmationIDOut
+ * @param productIDIn
+ * @return
+ */
+DWORD ConfirmationID::Generate(const std::string &installationIDIn, std::string &confirmationIDOut,
+ std::string &productIDIn)
{
- int version;
- unsigned char hardwareID[8];
- unsigned char installation_id[19]; // 10**45 < 256**19
- unsigned char productID[4];
+ DWORD version;
+ BYTE hardwareID[8];
+ BYTE installation_id[19]; // 10**45 < 256**19
+ BYTE productID[4];
- size_t installation_id_len = 0;
- const char *pid = installation_id_str;
+ BYTE installation_id_len = 0;
+ auto pid = installationIDIn.c_str();
- size_t count = 0, totalCount = 0;
+ BYTE count = 0, totalCount = 0;
unsigned check = 0;
- size_t i;
+ BYTE i;
+
+ Q_OWORD mod_inv;
+ memcpy(&mod_inv, &privateKey, sizeof(mod_inv));
for (; *pid; pid++)
{
@@ -232,7 +227,7 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
return ERR_INVALID_CHARACTER;
}
- if (count == 5 || p[1] == 0)
+ if (count == 5 || mod_inv.qword[0] == 0)
{
if (!count)
{
@@ -295,8 +290,8 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
{
QWORD HardwareID;
QWORD ProductIDLow;
- unsigned char ProductIDHigh;
- unsigned short KeySHA1;
+ BYTE ProductIDHigh;
+ WORD KeySHA1;
} parsed;
#pragma pack(pop)
@@ -331,9 +326,9 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
}
memcpy(&parsed, hardwareID, 8);
- productID[0] = stoi(productid.substr(0, 5));
+ productID[0] = stoi(productIDIn.substr(0, 5));
- std::string channelid = productid.substr(6, 3);
+ auto channelid = productIDIn.substr(6, 3);
char *p = &channelid[0];
for (; *p; p++)
{
@@ -342,21 +337,21 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
if (strcmp(&channelid[0], "OEM") == 0)
{
- productID[1] = stoi(productid.substr(12, 3));
- productID[2] = (stoi(productid.substr(15, 1)) * 100000) + stoi(productid.substr(18, 5));
+ productID[1] = stoi(productIDIn.substr(12, 3));
+ productID[2] = (stoi(productIDIn.substr(15, 1)) * 100000) + stoi(productIDIn.substr(18, 5));
productID[2] = calculateCheckDigit(productID[2]);
- productID[3] = ((stoi(productid.substr(10, 2))) * 1000) + productID[3];
+ productID[3] = ((stoi(productIDIn.substr(10, 2))) * 1000) + productID[3];
}
else
{
- productID[1] = stoi(productid.substr(6, 3));
- productID[2] = stoi(productid.substr(10, 7));
- productID[3] = stoi(productid.substr(18, 5));
+ productID[1] = stoi(productIDIn.substr(6, 3));
+ productID[2] = stoi(productIDIn.substr(10, 7));
+ productID[3] = stoi(productIDIn.substr(18, 5));
}
// fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
}
- unsigned char keybuf[16];
+ BYTE keybuf[16];
memcpy(keybuf, &parsed.HardwareID, 8);
QWORD productIdMixed =
@@ -364,34 +359,25 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
memcpy(keybuf + 8, &productIdMixed, 8);
TDivisor d;
- unsigned char attempt;
+ BYTE attempt;
- union {
- unsigned char buffer[14];
- struct
- {
- QWORD lo;
- QWORD hi;
- };
- } ulowhi;
+ Q_OWORD ulowhi;
+ memset(&ulowhi, 0, sizeof(ulowhi));
for (attempt = 0; attempt <= 0x80; attempt++)
{
- ulowhi.lo = this->u[0];
- ulowhi.hi = this->u[1];
-
if (isXPBrand)
{
- ulowhi.buffer[7] = attempt;
+ ulowhi.byte[7] = attempt;
}
else if (isOffice)
{
- ulowhi.buffer[6] = attempt;
+ ulowhi.byte[6] = attempt;
}
- Mix(ulowhi.buffer, 14, keybuf, 16);
- QWORD x2 = residue->ui128_quotient_mod(ulowhi.lo, ulowhi.hi);
- QWORD x1 = ulowhi.lo - x2 * MOD;
+ Mix(ulowhi.byte, 14, keybuf, 16);
+ QWORD x2 = residue->ui128_quotient_mod(ulowhi.qword[0], ulowhi.qword[1]);
+ QWORD x1 = ulowhi.qword[0] - x2 * MOD;
x2++;
d.u[0] = residue->sub(residue->mul(x1, x1), residue->mul(NON_RESIDUE, residue->mul(x2, x2)));
@@ -407,31 +393,26 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
return ERR_UNLUCKY;
}
- divisor->mul128(&d, u[0], u[1], &d);
+ Q_OWORD priv;
+ memcpy(&priv, &privateKey, sizeof(priv));
- union {
- struct
- {
- QWORD encoded_lo, encoded_hi;
- };
- struct
- {
- uint32_t encoded[4];
- };
- } e;
+ divisor->mul128(&d, priv.qword[0], priv.qword[1], &d);
+
+ Q_OWORD e;
+ memset(&e, 0, sizeof(e));
if (d.u[0] == BAD)
{
// we can not get the zero divisor, actually...
- e.encoded_lo = residue->__umul128(MOD + 2, MOD, &e.encoded_hi);
+ e.qword[0] = residue->__umul128(MOD + 2, MOD, &e.qword[1]);
}
else if (d.u[1] == BAD)
{
// O(1/MOD) chance
// encoded = (unsigned __int128)(MOD + 1) * d.u[0] + MOD; // * MOD + d.u[0] is fine too
- e.encoded_lo = residue->__umul128(MOD + 1, d.u[0], &e.encoded_hi);
- e.encoded_lo += MOD;
- e.encoded_hi += (e.encoded_lo < MOD);
+ e.qword[0] = residue->__umul128(MOD + 1, d.u[0], &e.qword[1]);
+ e.qword[0] += MOD;
+ e.qword[1] += (e.qword[0] < MOD);
}
else
{
@@ -443,9 +424,9 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
{
x2 = residue->sqrt(residue->mul(x2sqr, residue->inv(NON_RESIDUE)));
assert(x2 != BAD);
- e.encoded_lo = residue->__umul128(MOD + 1, MOD + x2, &e.encoded_hi);
- e.encoded_lo += x1;
- e.encoded_hi += (e.encoded_lo < x1);
+ e.qword[0] = residue->__umul128(MOD + 1, MOD + x2, &e.qword[1]);
+ e.qword[0] += x1;
+ e.qword[1] += (e.qword[0] < x1);
}
else
{
@@ -468,28 +449,34 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
x2a = tmp;
}
- e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi);
- e.encoded_lo += x2a;
- e.encoded_hi += (e.encoded_lo < x2a);
+ e.qword[0] = residue->__umul128(MOD + 1, x1a, &e.qword[1]);
+ e.qword[0] += x2a;
+ e.qword[1] += (e.qword[0] < x2a);
}
}
- unsigned char decimal[35];
+ BYTE decimal[35];
for (i = 0; i < 35; i++)
{
- unsigned c = e.encoded[3] % 10;
- e.encoded[3] /= 10;
- unsigned c2 = ((QWORD)c << 32 | e.encoded[2]) % 10;
- e.encoded[2] = ((QWORD)c << 32 | e.encoded[2]) / 10;
- unsigned c3 = ((QWORD)c2 << 32 | e.encoded[1]) % 10;
- e.encoded[1] = ((QWORD)c2 << 32 | e.encoded[1]) / 10;
- unsigned c4 = ((QWORD)c3 << 32 | e.encoded[0]) % 10;
- e.encoded[0] = ((QWORD)c3 << 32 | e.encoded[0]) / 10;
+ unsigned c = e.byte[3] % 10;
+ e.byte[3] /= 10;
+
+ unsigned c2 = ((QWORD)c << 32 | e.byte[2]) % 10;
+ e.byte[2] = ((QWORD)c << 32 | e.byte[2]) / 10;
+
+ unsigned c3 = ((QWORD)c2 << 32 | e.byte[1]) % 10;
+ e.byte[1] = ((QWORD)c2 << 32 | e.byte[1]) / 10;
+
+ unsigned c4 = ((QWORD)c3 << 32 | e.byte[0]) % 10;
+ e.byte[0] = ((QWORD)c3 << 32 | e.byte[0]) / 10;
+
decimal[34 - i] = c4;
}
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
- char *q = confirmation_id;
+
+ char *q = &confirmationIDOut[0];
+
for (i = 0; i < 7; i++)
{
if (i)
@@ -506,6 +493,6 @@ int ConfirmationID::Generate(const char *installation_id_str, char confirmation_
q[5] = ((p[0] + p[1] * 2 + p[2] + p[3] * 2 + p[4]) % 7) + '0';
q += 6;
}
- *q++ = 0;
+
return 0;
}
diff --git a/src/libumskt/confid/confid.h b/src/libumskt/confid/confid.h
index 09d933b..af54954 100644
--- a/src/libumskt/confid/confid.h
+++ b/src/libumskt/confid/confid.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/6/2023
+ * @FileCreated by Neo on 06/06/2023
* @Maintainer Neo
*/
@@ -45,121 +45,103 @@ typedef struct
QWORD v[2];
} TDivisor;
-enum ACTIVATION_ALGORITHM
-{
- WINDOWS = 0,
- OFFICE_XP = 1,
- OFFICE_2K3 = 2,
- OFFICE_2K7 = 3,
- PLUS_DME = 4,
-};
-
-EXPORT class ConfirmationID
+class ConfirmationID
{
QWORD MOD = 0, NON_RESIDUE = 0;
- QWORD f[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- QWORD p[4] = {0x0, 0x0, 0x0, 0x0};
- QWORD u[2] = {0x0, 0x0};
+ QWORD curve[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+ Q_OWORD privateKey;
- unsigned char iid_key[4] = {0x0, 0x0, 0x0, 0x0};
+ BYTE iid_key[4] = {0x0, 0x0, 0x0, 0x0};
BOOL isOffice = false, isXPBrand = false;
unsigned flagVersion = 0;
- public:
- void setFlagVersion(unsigned int flagVersion);
+ DWORD calculateCheckDigit(DWORD pid);
+ void decode_iid_new_version(BYTE *iid, BYTE *hwid, DWORD *version);
+ void Mix(BYTE *buffer, BYTE bufSize, const BYTE *key, BYTE keySize);
+ void Unmix(BYTE *buffer, BYTE bufSize, const BYTE *key, BYTE keySize);
- private:
- int calculateCheckDigit(int pid);
- void decode_iid_new_version(unsigned char *iid, unsigned char *hwid, int *version);
- void Mix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize);
- void Unmix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize);
+ class Divisor
+ {
+ ConfirmationID *parent;
- friend class Residue;
- Residue *residue;
-
- friend class Polynomial;
- Polynomial *polynomial;
+ public:
+ explicit Divisor(ConfirmationID *p)
+ {
+ parent = p;
+ }
+ int find_divisor_v(TDivisor *d);
+ void add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst);
+ void mul(const TDivisor *src, QWORD mult, TDivisor *dst);
+ void mul128(const TDivisor *src, QWORD mult_lo, QWORD mult_hi, TDivisor *dst);
+ int u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2]);
+ };
friend class Divisor;
+
+ class Residue
+ {
+ ConfirmationID *parent;
+
+ public:
+ explicit Residue(ConfirmationID *p)
+ {
+ parent = p;
+ }
+
+ QWORD add(QWORD x, QWORD y);
+ QWORD sub(QWORD x, QWORD y);
+ QWORD __umul128(QWORD a, QWORD b, QWORD *hi);
+ QWORD ui128_quotient_mod(QWORD lo, QWORD hi);
+ QWORD mul(QWORD x, QWORD y);
+ QWORD pow(QWORD x, QWORD y);
+ QWORD inverse(QWORD u, QWORD v);
+ QWORD inv(QWORD x);
+ QWORD sqrt(QWORD what);
+ };
+ friend class Residue;
+
+ class Polynomial
+ {
+ ConfirmationID *parent;
+
+ public:
+ explicit Polynomial(ConfirmationID *p)
+ {
+ parent = p;
+ }
+
+ int mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[]);
+ int div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient);
+ void xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg, QWORD gcd[3], int *pmult1deg,
+ QWORD mult1[3], int *pmult2deg, QWORD mult2[3]);
+ };
+ friend class Polynomial;
+
+ Residue *residue;
+ Polynomial *polynomial;
Divisor *divisor;
public:
- int Generate(const char *installation_id_str, char confirmation_id[49], std::string productid);
-
- void setMod(QWORD mod);
- void setNonResidue(QWORD nonResidue);
- void setPValues(QWORD p0, QWORD p1, QWORD p2, QWORD p3);
- void setPValues(QWORD pValues[4]);
- void setFValues(QWORD f0, QWORD f1, QWORD f2, QWORD f3, QWORD f4, QWORD f5);
- void setFValues(QWORD fValues[6]);
- void setIsOffice(BOOL isOffice);
- void setIsXPBrand(BOOL isXpBrand);
-
ConfirmationID()
{
residue = new Residue(this);
polynomial = new Polynomial(this);
divisor = new Divisor(this);
+ privateKey.qword[0] = privateKey.qword[1] = 0x00;
}
+ BOOL LoadHyperellipticCurve(QWORD x0, QWORD x1, QWORD x2, QWORD x3, QWORD x4, QWORD x5, Q_OWORD priv,
+ QWORD modulous, QWORD nonresidue, BOOL isOffice, BOOL isXPBrand, BYTE flagVersion);
+
+ BOOL LoadHyperellipticCurve(QWORD *f, Q_OWORD priv, QWORD modulous, QWORD nonresidue, BOOL isOffice, BOOL isXPBrand,
+ BYTE flagVersion);
+
+ DWORD Generate(const std::string &installation_id_str, std::string &confirmation_id, std::string &productid);
+
~ConfirmationID()
{
delete residue, polynomial, divisor;
}
};
-class Residue
-{
- ConfirmationID *parent;
-
- public:
- explicit Residue(ConfirmationID *in)
- {
- parent = in;
- }
-
- QWORD add(QWORD x, QWORD y);
- QWORD sub(QWORD x, QWORD y);
- QWORD __umul128(QWORD a, QWORD b, QWORD *hi);
- QWORD ui128_quotient_mod(QWORD lo, QWORD hi);
- QWORD mul(QWORD x, QWORD y);
- QWORD pow(QWORD x, QWORD y);
- QWORD inverse(QWORD u, QWORD v);
- QWORD inv(QWORD x);
- QWORD sqrt(QWORD what);
-};
-
-class Polynomial
-{
- ConfirmationID *parent;
-
- public:
- explicit Polynomial(ConfirmationID *in)
- {
- parent = in;
- }
-
- int mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[]);
- int div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient);
- void xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg, QWORD gcd[3], int *pmult1deg,
- QWORD mult1[3], int *pmult2deg, QWORD mult2[3]);
- int u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2]);
-};
-
-class Divisor
-{
- ConfirmationID *parent;
-
- public:
- explicit Divisor(ConfirmationID *in)
- {
- parent = in;
- }
-
- int find_divisor_v(TDivisor *d);
- void add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst);
- void mul(const TDivisor *src, QWORD mult, TDivisor *dst);
- void mul128(const TDivisor *src, QWORD mult_lo, QWORD mult_hi, TDivisor *dst);
-};
-
#endif // UMSKT_CONFID_H
diff --git a/src/libumskt/confid/divisor.cpp b/src/libumskt/confid/divisor.cpp
index 8709a6e..c0cc63b 100644
--- a/src/libumskt/confid/divisor.cpp
+++ b/src/libumskt/confid/divisor.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -22,21 +22,20 @@
#include "confid.h"
-int Divisor::find_divisor_v(TDivisor *d)
+int ConfirmationID::ConfirmationID::Divisor::find_divisor_v(TDivisor *d)
{
- // u | v^2 - f
+ // u | v^2 - curve
// u = u0 + u1*x + x^2
- // f%u = f0 + f1*x
+ // curve%u = f0 + f1*x
QWORD v1, f2[6];
- for (int i = 0; i < 6; i++)
+ for (BYTE i = 0; i < 6; i++)
{
- f2[i] = parent->f[i];
+ f2[i] = parent->curve[i];
}
- const QWORD u0 = d->u[0];
- const QWORD u1 = d->u[1];
- for (int j = 4; j--;)
+ const QWORD u0 = d->u[0], u1 = d->u[1];
+ for (BYTE j = 4; j--;)
{
f2[j] = parent->residue->sub(f2[j], parent->residue->mul(u0, f2[j + 2]));
f2[j + 1] = parent->residue->sub(f2[j + 1], parent->residue->mul(u1, f2[j + 2]));
@@ -50,8 +49,7 @@ int Divisor::find_divisor_v(TDivisor *d)
// v0^2 = f0 + u0*v1^2 = (f1 + u1*v1^2)^2 / (2*v1)^2
// (f1^2) + 2*(f1*u1-2*f0) * v1^2 + (u1^2-4*u0) * v1^4 = 0
// v1^2 = ((2*f0-f1*u1) +- 2*sqrt(-f0*f1*u1 + f0^2 + f1^2*u0))) / (u1^2-4*u0)
- const QWORD f0 = f2[0];
- const QWORD f1 = f2[1];
+ const QWORD f0 = f2[0], f1 = f2[1];
const QWORD u0double = parent->residue->add(u0, u0);
const QWORD coeff2 = parent->residue->sub(parent->residue->mul(u1, u1), parent->residue->add(u0double, u0double));
const QWORD coeff1 = parent->residue->sub(parent->residue->add(f0, f0), parent->residue->mul(f1, u1));
@@ -63,7 +61,7 @@ int Divisor::find_divisor_v(TDivisor *d)
if (f1 == 0)
{
// impossible
- // printf("bad f(), double root detected\n");
+ // printf("bad curve(), double root detected\n");
}
return 0;
}
@@ -109,15 +107,17 @@ int Divisor::find_divisor_v(TDivisor *d)
return 1;
}
-int Divisor::u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2])
+int ConfirmationID::ConfirmationID::Divisor::u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2])
{
if (src->u[1] != BAD)
{
polyu[0] = src->u[0];
polyu[1] = src->u[1];
polyu[2] = 1;
+
polyv[0] = src->v[0];
polyv[1] = src->v[1];
+
return 2;
}
@@ -125,8 +125,10 @@ int Divisor::u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2])
{
polyu[0] = src->u[0];
polyu[1] = 1;
+
polyv[0] = src->v[0];
polyv[1] = 0;
+
return 1;
}
@@ -136,7 +138,7 @@ int Divisor::u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2])
return 0;
}
-void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
+void ConfirmationID::Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
{
QWORD u1[3], u2[3], v1[2], v2[2];
int u1deg = u2poly(src1, u1, v1);
@@ -182,8 +184,8 @@ void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
QWORD v[7], tmp[7];
int vdeg, tmpdeg;
- // c1*(e1*u1*v2 + e2*u2*v1) + c2*(v1*v2 + f)
- // c1*(e1*u1*(v2-v1) + d1*v1) + c2*(v1*v2 + f)
+ // c1*(e1*u1*v2 + e2*u2*v1) + c2*(v1*v2 + curve)
+ // c1*(e1*u1*(v2-v1) + d1*v1) + c2*(v1*v2 + curve)
v[0] = parent->residue->sub(v2[0], v1[0]);
v[1] = parent->residue->sub(v2[1], v1[1]);
tmpdeg = parent->polynomial->mul(e1deg, e1, 1, v, -1, tmp);
@@ -195,7 +197,7 @@ void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
v[i] = parent->residue->mul(v[i], c1[0]);
}
- memcpy(tmp, parent->f, 6 * sizeof(parent->f[0]));
+ memcpy(tmp, parent->curve, 6 * sizeof(parent->curve[0]));
tmpdeg = 5;
tmpdeg = parent->polynomial->mul(1, v1, 1, v2, tmpdeg, tmp);
vdeg = parent->polynomial->mul(c2deg, c2, tmpdeg, tmp, vdeg, v);
@@ -223,11 +225,11 @@ void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
{
assert(udeg <= 4);
assert(vdeg <= 3);
- // u' = monic((f-v^2)/u), v'=-v mod u'
+ // u' = monic((curve-v^2)/u), v'=-v mod u'
tmpdeg = parent->polynomial->mul(vdeg, v, vdeg, v, -1, tmp);
for (i = 0; i <= tmpdeg && i <= 5; i++)
{
- tmp[i] = parent->residue->sub(parent->f[i], tmp[i]);
+ tmp[i] = parent->residue->sub(parent->curve[i], tmp[i]);
}
for (; i <= tmpdeg; i++)
@@ -237,7 +239,7 @@ void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
for (; i <= 5; i++)
{
- tmp[i] = parent->f[i];
+ tmp[i] = parent->curve[i];
}
tmpdeg = i - 1;
@@ -288,7 +290,7 @@ void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
#define divisor_double(src, dst) add(src, src, dst)
-void Divisor::mul(const TDivisor *src, QWORD mult, TDivisor *dst)
+void ConfirmationID::Divisor::mul(const TDivisor *src, QWORD mult, TDivisor *dst)
{
if (mult == 0)
{
@@ -317,7 +319,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 ConfirmationID::Divisor::mul128(const TDivisor *src, QWORD mult_lo, QWORD mult_hi, TDivisor *dst)
{
if (mult_lo == 0 && mult_hi == 0)
{
diff --git a/src/libumskt/confid/polynomial.cpp b/src/libumskt/confid/polynomial.cpp
index cf3b888..2d37891 100644
--- a/src/libumskt/confid/polynomial.cpp
+++ b/src/libumskt/confid/polynomial.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -23,7 +23,8 @@
#include "confid.h"
// generic short slow code
-int Polynomial::mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[])
+int ConfirmationID::Polynomial::mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg,
+ QWORD result[])
{
if (adeg < 0 || bdeg < 0)
{
@@ -55,7 +56,7 @@ int Polynomial::mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int re
return resultprevdeg;
}
-int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient)
+int ConfirmationID::Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient)
{
assert(bdeg >= 0);
assert(b[bdeg] == 1);
@@ -84,8 +85,8 @@ int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD
return i;
}
-void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg, QWORD gcd[3],
- int *pmult1deg, QWORD mult1[3], int *pmult2deg, QWORD mult2[3])
+void ConfirmationID::Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg,
+ QWORD gcd[3], int *pmult1deg, QWORD mult1[3], int *pmult2deg, QWORD mult2[3])
{
int sdeg = -1;
QWORD s[3] = {0, 0, 0};
@@ -119,43 +120,56 @@ void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], in
{
unsigned tmp;
int tmpi;
+
tmp = rdeg;
rdeg = gcddeg;
gcddeg = tmp;
+
tmpi = sdeg;
sdeg = mult1deg;
mult1deg = tmpi;
+
tmpi = tdeg;
tdeg = mult2deg;
mult2deg = tmpi;
+
QWORD tmp2;
tmp2 = r[0];
r[0] = gcd[0];
gcd[0] = tmp2;
+
tmp2 = r[1];
r[1] = gcd[1];
gcd[1] = tmp2;
+
tmp2 = r[2];
r[2] = gcd[2];
gcd[2] = tmp2;
+
tmp2 = s[0];
s[0] = mult1[0];
mult1[0] = tmp2;
+
tmp2 = s[1];
s[1] = mult1[1];
mult1[1] = tmp2;
+
tmp2 = s[2];
s[2] = mult1[2];
mult1[2] = tmp2;
+
tmp2 = t[0];
t[0] = mult2[0];
mult2[0] = tmp2;
+
tmp2 = t[1];
t[1] = mult2[1];
mult2[1] = tmp2;
+
tmp2 = t[2];
t[2] = mult2[2];
mult2[2] = tmp2;
+
continue;
}
diff --git a/src/libumskt/confid/residue.cpp b/src/libumskt/confid/residue.cpp
index 70ecd97..742c366 100644
--- a/src/libumskt/confid/residue.cpp
+++ b/src/libumskt/confid/residue.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -24,17 +24,20 @@
#if defined(__x86_64__) || defined(_M_AMD64) || defined(__aarch64__) || (defined(__arm64__) && defined(__APPLE__))
#ifdef __GNUC__
-inline QWORD Residue::__umul128(QWORD a, QWORD b, QWORD *hi)
+inline QWORD ConfirmationID::Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi)
{
- OWORD r = (OWORD)a * (OWORD)b;
- *hi = r >> 64;
+ OWORD r = (OWORD)multiplier * (OWORD)multiplicand;
+ *product_hi = r >> 64;
return (QWORD)r;
}
#else
-#define __umul128 _umul128
+inline QWORD ConfirmationID::Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi)
+{
+ return _umul128(multiplier, multiplicand, product_hi);
+}
#endif
#elif defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(__EMSCRIPTEN__)
-inline QWORD Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi)
+inline QWORD ConfirmationID::Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi)
{
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
@@ -63,17 +66,14 @@ inline QWORD Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *pro
#error Unknown architecture detected - please edit confid.cpp to tailor __umul128() your architecture
#endif
-QWORD Residue::ui128_quotient_mod(QWORD lo, QWORD hi)
+QWORD ConfirmationID::Residue::ui128_quotient_mod(QWORD lo, QWORD hi)
{
// hi:lo * ceil(2**170/MOD) >> (64 + 64 + 42)
QWORD prod1;
- __umul128(lo, parent->p0, &prod1);
+ __umul128(lo, parent->privateKey.qword[0], &prod1);
- QWORD part1hi, part1lo;
- part1lo = __umul128(lo, parent->p1, &part1hi);
-
- QWORD part2hi, part2lo;
- part2lo = __umul128(hi, parent->p2, &part2hi);
+ QWORD part1hi, part1lo = __umul128(lo, parent->privateKey.qword[1], &part1hi);
+ QWORD part2hi, part2lo = __umul128(hi, parent->privateKey.qword[0], &part2hi);
QWORD sum1 = part1lo + part2lo;
unsigned sum1carry = (sum1 < part1lo);
@@ -81,24 +81,22 @@ QWORD Residue::ui128_quotient_mod(QWORD lo, QWORD hi)
sum1carry += (sum1 < prod1);
QWORD prod2 = part1hi + part2hi + sum1carry;
- QWORD prod3hi, prod3lo;
- prod3lo = __umul128(hi, parent->p3, &prod3hi);
+ QWORD prod3hi, prod3lo = __umul128(hi, parent->privateKey.qword[1], &prod3hi);
prod3lo += prod2;
prod3hi += (prod3lo < prod2);
return (prod3lo >> 42) | (prod3hi << 22);
}
-QWORD Residue::mul(QWORD x, QWORD y)
+QWORD ConfirmationID::Residue::mul(QWORD x, QWORD y)
{
// * ceil(2**170/MOD) = 0x2d351 c6d04f8b|604fa6a1 c6346a87 for (p-1)*(p-1) max
- QWORD hi;
- QWORD lo = __umul128(x, y, &hi);
+ QWORD hi, lo = __umul128(x, y, &hi);
QWORD quotient = ui128_quotient_mod(lo, hi);
return lo - quotient * parent->MOD;
}
-QWORD Residue::pow(QWORD x, QWORD y)
+QWORD ConfirmationID::Residue::pow(QWORD x, QWORD y)
{
if (y == 0)
{
@@ -125,7 +123,7 @@ QWORD Residue::pow(QWORD x, QWORD y)
return res;
}
-QWORD Residue::add(QWORD x, QWORD y)
+QWORD ConfirmationID::Residue::add(QWORD x, QWORD y)
{
QWORD z = x + y;
// z = z - (z >= MOD ? MOD : 0);
@@ -136,7 +134,7 @@ QWORD Residue::add(QWORD x, QWORD y)
return z;
}
-QWORD Residue::sub(QWORD x, QWORD y)
+QWORD ConfirmationID::Residue::sub(QWORD x, QWORD y)
{
QWORD z = x - y;
// z += (x < y ? MOD : 0);
@@ -147,7 +145,7 @@ QWORD Residue::sub(QWORD x, QWORD y)
return z;
}
-QWORD Residue::inverse(QWORD u, QWORD v)
+QWORD ConfirmationID::Residue::inverse(QWORD u, QWORD v)
{
// assert(u);
int64_t tmp;
@@ -168,13 +166,13 @@ QWORD Residue::inverse(QWORD u, QWORD v)
return xu;
}
-QWORD Residue::inv(QWORD x)
+QWORD ConfirmationID::Residue::inv(QWORD x)
{
return inverse(x, parent->MOD);
// return residue_pow(x, MOD - 2);
}
-QWORD Residue::sqrt(QWORD what)
+QWORD ConfirmationID::Residue::sqrt(QWORD what)
{
if (!what)
{
@@ -195,6 +193,7 @@ QWORD Residue::sqrt(QWORD what)
x = pow(what, (q - 1) / 2);
b = mul(mul(what, x), x);
x = mul(what, x);
+
while (b != 1)
{
QWORD m = 0, b2 = b;
@@ -224,4 +223,4 @@ QWORD Residue::sqrt(QWORD what)
}
return x;
-}
\ No newline at end of file
+}
diff --git a/src/libumskt/debugoutput.cpp b/src/libumskt/debugoutput.cpp
index 824d12f..9b5d8c6 100644
--- a/src/libumskt/debugoutput.cpp
+++ b/src/libumskt/debugoutput.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,18 +16,27 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/25/2023
+ * @FileCreated by Neo on 06/25/2023
* @Maintainer Neo
*/
#include "libumskt.h"
#ifdef _WIN32
-std::FILE *UMSKT::debug = std::fopen("NUL:", "w");
+// this seems janky but it works, and doesn't use storage that would otherwise get clobbered
+std::FILE *getFileStreamToNul()
+{
+ fopen_s(&UMSKT::debug, "nul", "w");
+ return UMSKT::debug;
+}
+std::FILE *UMSKT::debug = getFileStreamToNul();
#else
std::FILE *UMSKT::debug = std::fopen("/dev/null", "w");
#endif
+BOOL UMSKT::VERBOSE;
+BOOL UMSKT::DEBUG;
+
void UMSKT::setDebugOutput(std::FILE *input)
{
debug = input;
diff --git a/src/libumskt/libumskt.cpp b/src/libumskt/libumskt.cpp
index 608b22b..6bb14f5 100644
--- a/src/libumskt/libumskt.cpp
+++ b/src/libumskt/libumskt.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/25/2023
+ * @FileCreated by Neo on 06/25/2023
* @Maintainer Neo
*/
@@ -27,48 +27,145 @@
#include "pidgen3/BINK2002.h"
#include "pidgen3/PIDGEN3.h"
-FNEXPORT int ConfirmationID_Generate(const char *installation_id_str, char confirmation_id[49], int mode,
- std::string productid)
+FNEXPORT BOOL LIBUMSKT_SET_DEBUG_OUTPUT(void *filestream)
{
- return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid);
+ char buffer[7];
+ memcpy(buffer, filestream, 6);
+ buffer[6] = 0;
+ auto buff_string = std::string(buffer);
+
+ if (strcasecmp("STDOUT", &buffer[0]) != 0)
+ {
+ UMSKT::debug = stdout;
+ return true;
+ }
+ else if (strcasecmp("STDERR", &buffer[0]) != 0)
+ {
+ UMSKT::debug = stderr;
+ return true;
+ }
+
+ return false;
}
-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 void *CONFID_INIT()
{
- return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel,
- publicKeyYSel, genPoint, pubPoint);
+ auto cid = new ConfirmationID();
+
+ // cid->LoadHyperellipticCurve(0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, 0);
+
+ return cid;
}
-FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25])
+FNEXPORT BYTE CONFID_GENERATE(void *cidIn, const char *installation_id_str, char *&confirmation_id, char *productid)
{
- return PIDGEN3::BINK1998::Verify(eCurve, basePoint, publicKey, pKey);
+ auto *cid((ConfirmationID *)cidIn);
+
+ std::string str, confid(confirmation_id), productids(productid);
+ auto retval = cid->Generate(str, confid, productids);
+
+ return retval;
}
-FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
- DWORD pSerial, BOOL pUpgrade, char (&pKey)[25])
+FNEXPORT BYTE CONFID_END(void *cidIn)
{
- return PIDGEN3::BINK1998::Generate(eCurve, basePoint, genOrder, privateKey, pSerial, pUpgrade, pKey);
+ auto *cid((ConfirmationID *)cidIn);
+ delete cid;
+
+ return true;
}
-FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25])
+// ---------------------------------------------
+
+FNEXPORT void *PIDGEN3_BINK1998_INIT(const char *p, const char *a, const char *b, const char *generatorX,
+ const char *generatorY, const char *publicKeyX, const char *publicKeyY,
+ const char *genOrder, const char *privateKey)
{
- return PIDGEN3::BINK2002::Verify(eCurve, basePoint, publicKey, cdKey);
+
+ auto *bink1998 = new BINK1998();
+
+ bink1998->LoadEllipticCurve(p, a, b, generatorX, generatorY, publicKeyX, publicKeyY, genOrder, privateKey);
+
+ return bink1998;
}
-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_INIT(const char *p, const char *a, const char *b, const char *generatorX,
+ const char *generatorY, const char *publicKeyX, const char *publicKeyY,
+ const char *genOrder, const char *privateKey, const char *authinfo)
{
- return PIDGEN3::BINK2002::Generate(eCurve, basePoint, genOrder, privateKey, pChannelID, pAuthInfo, pUpgrade, pKey);
+
+ auto bink2002 = new BINK2002();
+
+ bink2002->LoadEllipticCurve(p, a, b, generatorX, generatorY, publicKeyX, publicKeyY, genOrder, privateKey);
+
+ return bink2002;
}
-FNEXPORT int PIDGEN2_GenerateRetail(char *channelID, char *&keyout)
+FNEXPORT BOOL PIDGEN3_Generate(void *&ptrIn, char *&pKeyOut, int pKeySizeIn)
{
- return PIDGEN2::GenerateRetail(channelID, keyout);
+ auto *p3((PIDGEN3 *)ptrIn);
+
+ std::string str;
+ BOOL retval = p3->Generate(str);
+
+ if (pKeySizeIn > str.length() + 1)
+ {
+ return false;
+ }
+
+ memcpy(pKeyOut, &str[0], str.length());
+ pKeyOut[str.length()] = 0;
+
+ return retval;
}
-FNEXPORT int PIDGEN2_GenerateOEM(char *year, char *day, char *oem, char *keyout)
+FNEXPORT BOOL PIDGEN3_Verify(void *&ptrIn, char *pKeyIn)
{
- return PIDGEN2::GenerateOEM(year, day, oem, keyout);
+ auto *p3((PIDGEN3 *)ptrIn);
+ std::string str(pKeyIn);
+
+ BOOL retval = p3->Verify(str);
+
+ return retval;
}
+
+FNEXPORT void PIDGEN3_END(void *ptrIn)
+{
+ auto *p3((PIDGEN3 *)ptrIn);
+ delete p3;
+}
+
+// ---------------------------------------------
+
+FNEXPORT BOOL PIDGEN2_INIT()
+{
+ return true;
+}
+
+FNEXPORT BOOL PIDGEN2_GENERATE()
+{
+ return true;
+}
+
+FNEXPORT BOOL PIDGEN2_END()
+{
+ return true;
+}
+
+FNEXPORT BOOL PIDGEN2_GenerateRetail(char *channelID, char *&keyout)
+{
+ auto P2 = new PIDGEN2();
+ BOOL retval = P2->GenerateRetail(channelID, keyout);
+ delete P2;
+ return retval;
+}
+
+FNEXPORT BOOL PIDGEN2_GenerateOEM(char *year, char *day, char *oem, char *&keyout)
+{
+ auto P2 = new PIDGEN2();
+ BOOL retval = P2->GenerateOEM(year, day, oem, keyout);
+ delete P2;
+ return retval;
+}
\ No newline at end of file
diff --git a/src/libumskt/libumskt.h b/src/libumskt/libumskt.h
index 1631dbd..d73127e 100644
--- a/src/libumskt/libumskt.h
+++ b/src/libumskt/libumskt.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/24/2023
+ * @FileCreated by Neo on 06/24/2023
* @Maintainer Neo
*/
@@ -63,11 +63,19 @@ class UMSKT
{
public:
static std::FILE *debug;
- class PIDGEN2;
- class PIDGEN3;
- class ConfigurationID;
+ static BOOL VERBOSE;
+ static BOOL DEBUG;
static void setDebugOutput(std::FILE *input);
+ template static T getRandom()
+ {
+ T retval;
+ BIGNUM *bnrand = BN_new();
+ BN_rand(bnrand, sizeof(T) * 8, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
+ BN_bn2lebinpad(bnrand, (unsigned char *)&retval, sizeof(T));
+ BN_free(bnrand);
+ return retval;
+ }
};
#endif // UMSKT_LIBUMSKT_H
diff --git a/src/libumskt/pidgen2/PIDGEN2.cpp b/src/libumskt/pidgen2/PIDGEN2.cpp
index e9c26c8..677663d 100644
--- a/src/libumskt/pidgen2/PIDGEN2.cpp
+++ b/src/libumskt/pidgen2/PIDGEN2.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -22,9 +22,6 @@
#include "PIDGEN2.h"
-const char *channelIDBlacklist[7] = {"333", "444", "555", "666", "777", "888", "999"};
-const char *validYears[8] = {"95", "96", "97", "98", "99", "00", "01", "02"};
-
bool PIDGEN2::isNumericString(char *input)
{
for (int i = 0; i < strlen(input); i++)
diff --git a/src/libumskt/pidgen2/PIDGEN2.h b/src/libumskt/pidgen2/PIDGEN2.h
index 7c4bd0d..e6d4ffb 100644
--- a/src/libumskt/pidgen2/PIDGEN2.h
+++ b/src/libumskt/pidgen2/PIDGEN2.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -25,18 +25,26 @@
#include "../libumskt.h"
-EXPORT class PIDGEN2
+class PIDGEN2
{
+ DWORD year;
+ DWORD day;
+ BOOL isOEM;
+ BOOL isOffice;
+
+ static constexpr char channelIDBlacklist[7][4] = {"333", "444", "555", "666", "777", "888", "999"};
+ static constexpr char validYears[8][3] = {"95", "96", "97", "98", "99", "00", "01", "02"};
+
public:
- static bool isNumericString(char *input);
- static bool isValidChannelID(char *channelID);
- static bool isValidOEMID(char *OEMID);
- static bool isValidYear(char *year);
- static bool isValidDay(char *day);
- static bool isValidRetailProductID(char *productID);
- static int addDigits(char *input);
- static int GenerateRetail(char *channelID, char *&keyout);
- static int GenerateOEM(char *year, char *day, char *oem, char *&keyout);
+ BOOL isNumericString(char *input);
+ BOOL isValidChannelID(char *channelID);
+ BOOL isValidOEMID(char *OEMID);
+ BOOL isValidYear(char *year);
+ BOOL isValidDay(char *day);
+ BOOL isValidRetailProductID(char *productID);
+ int addDigits(char *input);
+ int GenerateRetail(char *channelID, char *&keyout);
+ int GenerateOEM(char *year, char *day, char *oem, char *&keyout);
};
#endif // UMSKT_PIDGEN2_H
diff --git a/src/libumskt/pidgen3/BINK1998.cpp b/src/libumskt/pidgen3/BINK1998.cpp
index a1bfbd4..6c4e9f7 100644
--- a/src/libumskt/pidgen3/BINK1998.cpp
+++ b/src/libumskt/pidgen3/BINK1998.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -29,62 +29,81 @@
#include "BINK1998.h"
-/* Unpacks a Windows XP-like Product Key. */
-void PIDGEN3::BINK1998::Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature)
+/**
+ * Unpacks a Windows XP-like Product Key.
+ *
+ * @param pRaw [out] *QWORD[2] raw product key output
+ **/
+BOOL BINK1998::Unpack(QWORD (&pRaw)[2])
{
// We're assuming that the quantity of information within the product key is at most 114 bits.
// log2(24^25) = 114.
// Upgrade = Bit 0
- pUpgrade = FIRSTNBITS(pRaw[0], 1);
+ isUpgrade = FIRSTNBITS(pRaw[0], 1);
// Serial = Bits [1..30] -> 30 bits
- pSerial = NEXTSNBITS(pRaw[0], 30, 1);
+ Serial = NEXTSNBITS(pRaw[0], 30, 1);
// Hash = Bits [31..58] -> 28 bits
- pHash = NEXTSNBITS(pRaw[0], 28, 31);
+ Hash = NEXTSNBITS(pRaw[0], 28, 31);
// Signature = Bits [59..113] -> 56 bits
- pSignature = FIRSTNBITS(pRaw[1], 51) << 5 | NEXTSNBITS(pRaw[0], 5, 59);
+ Signature = FIRSTNBITS(pRaw[1], 51) << 5 | NEXTSNBITS(pRaw[0], 5, 59);
+
+ return true;
}
-/* Packs a Windows XP-like Product Key. */
-void PIDGEN3::BINK1998::Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature)
+/**
+ * Packs a Windows XP-like Product Key.
+ *
+ * @param pRaw [in] *QWORD[2] raw product key input
+ **/
+BOOL BINK1998::Pack(QWORD (&pRaw)[2])
{
// The quantity of information the key provides is 114 bits.
// We're storing it in 2 64-bit quad-words with 14 trailing bits.
// 64 * 2 = 128
// Signature [114..59] <- Hash [58..31] <- Serial [30..1] <- Upgrade [0]
- pRaw[0] = FIRSTNBITS(pSignature, 5) << 59 | FIRSTNBITS(pHash, 28) << 31 | pSerial << 1 | pUpgrade;
- pRaw[1] = NEXTSNBITS(pSignature, 51, 5);
+ pRaw[0] = FIRSTNBITS(Signature, 5) << 59 | FIRSTNBITS(Hash, 28) << 31 | Serial << 1 | isUpgrade;
+ pRaw[1] = NEXTSNBITS(Signature, 51, 5);
+
+ return true;
}
-/* Verifies a Windows XP-like Product Key. */
-bool PIDGEN3::BINK1998::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25])
+/**
+ * Verifies a Windows XP-like Product Key.
+ *
+ * @param pKey [in]
+ *
+ * @return true if provided key validates against loaded curve
+ */
+BOOL BINK1998::Verify(std::string &pKey)
{
+ if (pKey.length() != 25)
+ {
+ return false;
+ }
+
BN_CTX *numContext = BN_CTX_new();
- QWORD pRaw[2]{}, pSignature;
-
- DWORD pData, pSerial, pHash;
-
- BOOL pUpgrade;
+ QWORD pRaw[2]{};
// Convert Base24 CD-key to bytecode.
- PIDGEN3::unbase24((BYTE *)pRaw, pKey);
+ unbase24((BYTE *)pRaw, pKey);
// Extract RPK, hash and signature from bytecode.
- Unpack(pRaw, pUpgrade, pSerial, pHash, pSignature);
+ Unpack(pRaw);
fmt::print(UMSKT::debug, "Validation results:\n");
- fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
- fmt::print(UMSKT::debug, " Serial: 0x{:08x}\n", pSerial);
- fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
- fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
+ fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", isUpgrade);
+ fmt::print(UMSKT::debug, " Serial: 0x{:08x}\n", Serial);
+ fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", Hash);
+ fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", Signature);
fmt::print(UMSKT::debug, "\n");
- pData = pSerial << 1 | pUpgrade;
+ DWORD pData = Serial << 1 | isUpgrade;
/*
*
@@ -101,8 +120,8 @@ bool PIDGEN3::BINK1998::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *
*
*/
- BIGNUM *e = BN_lebin2bn((BYTE *)&pHash, sizeof(pHash), nullptr),
- *s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr), *x = BN_new(), *y = BN_new();
+ BIGNUM *e = BN_lebin2bn((BYTE *)&Hash, sizeof(Hash), nullptr),
+ *s = BN_lebin2bn((BYTE *)&Signature, sizeof(Signature), nullptr), *x = BN_new(), *y = BN_new();
// Create 2 points on the elliptic curve.
EC_POINT *t = EC_POINT_new(eCurve);
@@ -149,21 +168,26 @@ bool PIDGEN3::BINK1998::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *
EC_POINT_free(p);
// If the computed hash checks out, the key is valid.
- return compHash == pHash;
+ return compHash == Hash;
}
-/* Generates a Windows XP-like Product Key. */
-void PIDGEN3::BINK1998::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
- DWORD pSerial, BOOL pUpgrade, char (&pKey)[25])
+/**
+ * Generates a Windows XP-like Product Key.
+ *
+ * @param pKey [out]
+ *
+ * @return true on success, false on fail
+ */
+BOOL BINK1998::Generate(std::string &pKey)
{
BN_CTX *numContext = BN_CTX_new();
BIGNUM *c = BN_new(), *s = BN_new(), *x = BN_new(), *y = BN_new();
- QWORD pRaw[2]{}, pSignature = 0;
+ QWORD pRaw[2]{};
// Data segment of the RPK.
- DWORD pData = pSerial << 1 | pUpgrade;
+ DWORD pData = Serial << 1 | isUpgrade;
do
{
@@ -225,20 +249,20 @@ void PIDGEN3::BINK1998::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *
BN_mod_add(s, s, c, genOrder, numContext);
// Translate resulting scalar into a 64-bit integer (the byte order is little-endian).
- BN_bn2lebinpad(s, (BYTE *)&pSignature, BN_num_bytes(s));
+ BN_bn2lebinpad(s, (BYTE *)&Signature, BN_num_bytes(s));
// Pack product key.
- Pack(pRaw, pUpgrade, pSerial, pHash, pSignature);
+ Pack(pRaw);
fmt::print(UMSKT::debug, "Generation results:\n");
- fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
- fmt::print(UMSKT::debug, " Serial: 0x{:08x}\n", pSerial);
- fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
- fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
+ fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", isUpgrade);
+ fmt::print(UMSKT::debug, " Serial: 0x{:08x}\n", Serial);
+ fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", Hash);
+ fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", Signature);
fmt::print(UMSKT::debug, "\n");
EC_POINT_free(r);
- } while (pSignature > BITMASK(55));
+ } while (Signature > BITMASK(55));
// ↑ ↑ ↑
// The signature can't be longer than 55 bits, else it will
// make the CD-key longer than 25 characters.
@@ -252,4 +276,6 @@ void PIDGEN3::BINK1998::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *
BN_free(y);
BN_CTX_free(numContext);
+
+ return true;
}
diff --git a/src/libumskt/pidgen3/BINK1998.h b/src/libumskt/pidgen3/BINK1998.h
index 65bf702..65e7e68 100644
--- a/src/libumskt/pidgen3/BINK1998.h
+++ b/src/libumskt/pidgen3/BINK1998.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/6/2023
+ * @FileCreated by Neo on 06/06/2023
* @Maintainer Neo
*/
@@ -25,17 +25,14 @@
#include "PIDGEN3.h"
-EXPORT class PIDGEN3::BINK1998
+class BINK1998 : public PIDGEN3
{
+
public:
- static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature);
-
- static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature);
-
- static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25]);
-
- static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial,
- BOOL pUpgrade, char (&pKey)[25]);
+ BOOL Unpack(QWORD (&pRaw)[2]) override;
+ BOOL Pack(QWORD (&pRaw)[2]) override;
+ BOOL Verify(std::string &pKey) override;
+ BOOL Generate(std::string &pKey) override;
};
#endif // UMSKT_BINK1998_H
diff --git a/src/libumskt/pidgen3/BINK2002.cpp b/src/libumskt/pidgen3/BINK2002.cpp
index ca87563..0942559 100644
--- a/src/libumskt/pidgen3/BINK2002.cpp
+++ b/src/libumskt/pidgen3/BINK2002.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -29,65 +29,75 @@
#include "BINK2002.h"
-/* Unpacks a Windows Server 2003-like Product Key. */
-void PIDGEN3::BINK2002::Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
- DWORD &pAuthInfo)
+/**
+ * Unpacks a Windows Server 2003-like Product Key.
+ *
+ * @param pRaw *QWORD[2] raw product key input
+ **/
+BOOL BINK2002::Unpack(QWORD (&pRaw)[2])
{
// We're assuming that the quantity of information within the product key is at most 114 bits.
// log2(24^25) = 114.
// Upgrade = Bit 0
- pUpgrade = FIRSTNBITS(pRaw[0], 1);
+ isUpgrade = FIRSTNBITS(pRaw[0], 1);
// Channel ID = Bits [1..10] -> 10 bits
- pChannelID = NEXTSNBITS(pRaw[0], 10, 1);
+ ChannelID = NEXTSNBITS(pRaw[0], 10, 1);
// Hash = Bits [11..41] -> 31 bits
- pHash = NEXTSNBITS(pRaw[0], 31, 11);
+ Hash = NEXTSNBITS(pRaw[0], 31, 11);
// Signature = Bits [42..103] -> 62 bits
// The quad-word signature overlaps AuthInfo in bits 104 and 105,
// hence Microsoft employs a secret technique called: Signature = HIDWORD(Signature) >> 2 | LODWORD(Signature)
- pSignature = NEXTSNBITS(pRaw[1], 30, 10) << 32 | FIRSTNBITS(pRaw[1], 10) << 22 | NEXTSNBITS(pRaw[0], 22, 42);
+ Signature = NEXTSNBITS(pRaw[1], 30, 10) << 32 | FIRSTNBITS(pRaw[1], 10) << 22 | NEXTSNBITS(pRaw[0], 22, 42);
// AuthInfo = Bits [104..113] -> 10 bits
- pAuthInfo = NEXTSNBITS(pRaw[1], 10, 40);
+ AuthInfo = NEXTSNBITS(pRaw[1], 10, 40);
+
+ return true;
}
-/* Packs a Windows Server 2003-like Product Key. */
-void PIDGEN3::BINK2002::Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature,
- DWORD pAuthInfo)
+/**
+ * Packs a Windows Server 2003-like Product Key.
+ *
+ * @param pRaw *QWORD[2] raw product key output
+ **/
+BOOL BINK2002::Pack(QWORD (&pRaw)[2])
{
// AuthInfo [113..104] <- Signature [103..42] <- Hash [41..11] <- Channel ID [10..1] <- Upgrade [0]
- pRaw[0] = FIRSTNBITS(pSignature, 22) << 42 | (QWORD)pHash << 11 | pChannelID << 1 | pUpgrade;
- pRaw[1] = FIRSTNBITS(pAuthInfo, 10) << 40 | NEXTSNBITS(pSignature, 40, 22);
+ pRaw[0] = FIRSTNBITS(Signature, 22) << 42 | (QWORD)Hash << 11 | ChannelID << 1 | isUpgrade;
+ pRaw[1] = FIRSTNBITS(AuthInfo, 10) << 40 | NEXTSNBITS(Signature, 40, 22);
+
+ return true;
}
-/* Verifies a Windows Server 2003-like Product Key. */
-bool PIDGEN3::BINK2002::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25])
+/**
+ * Verifies a Windows Server 2003-like Product Key.
+ *
+ * @param pKey
+ **/
+BOOL BINK2002::Verify(std::string &pKey)
{
BN_CTX *context = BN_CTX_new();
- QWORD bKey[2]{}, pSignature = 0;
-
- DWORD pData, pChannelID, pHash, pAuthInfo;
-
- BOOL pUpgrade;
+ QWORD bKey[2]{};
// Convert Base24 CD-key to bytecode.
- unbase24((BYTE *)bKey, cdKey);
+ unbase24((BYTE *)bKey, pKey.c_str());
// Extract product key segments from bytecode.
- Unpack(bKey, pUpgrade, pChannelID, pHash, pSignature, pAuthInfo);
+ Unpack(bKey);
- pData = pChannelID << 1 | pUpgrade;
+ DWORD pData = ChannelID << 1 | isUpgrade;
fmt::print(UMSKT::debug, "Validation results:\n");
- fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
- fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", pChannelID);
- fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
- fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
- fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo);
+ fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", isUpgrade);
+ fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", ChannelID);
+ fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", Hash);
+ fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", Signature);
+ fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", AuthInfo);
fmt::print(UMSKT::debug, "\n");
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, xBin[FIELD_BYTES_2003]{},
@@ -97,12 +107,12 @@ bool PIDGEN3::BINK2002::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *
msgBuffer[0x00] = 0x5D;
msgBuffer[0x01] = (pData & 0x00FF);
msgBuffer[0x02] = (pData & 0xFF00) >> 8;
- msgBuffer[0x03] = (pHash & 0x000000FF);
- msgBuffer[0x04] = (pHash & 0x0000FF00) >> 8;
- msgBuffer[0x05] = (pHash & 0x00FF0000) >> 16;
- msgBuffer[0x06] = (pHash & 0xFF000000) >> 24;
- msgBuffer[0x07] = (pAuthInfo & 0x00FF);
- msgBuffer[0x08] = (pAuthInfo & 0xFF00) >> 8;
+ msgBuffer[0x03] = (Hash & 0x000000FF);
+ msgBuffer[0x04] = (Hash & 0x0000FF00) >> 8;
+ msgBuffer[0x05] = (Hash & 0x00FF0000) >> 16;
+ msgBuffer[0x06] = (Hash & 0xFF000000) >> 24;
+ msgBuffer[0x07] = (AuthInfo & 0x00FF);
+ msgBuffer[0x08] = (AuthInfo & 0xFF00) >> 8;
msgBuffer[0x09] = 0x00;
msgBuffer[0x0A] = 0x00;
@@ -130,11 +140,10 @@ bool PIDGEN3::BINK2002::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *
*/
BIGNUM *e = BN_lebin2bn((BYTE *)&iSignature, sizeof(iSignature), nullptr),
- *s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr), *x = BN_new(), *y = BN_new();
+ *s = BN_lebin2bn((BYTE *)&Signature, sizeof(Signature), nullptr), *x = BN_new(), *y = BN_new();
// Create 2 points on the elliptic curve.
- EC_POINT *p = EC_POINT_new(eCurve);
- EC_POINT *t = EC_POINT_new(eCurve);
+ EC_POINT *p = EC_POINT_new(eCurve), *t = EC_POINT_new(eCurve);
// t = sG
EC_POINT_mul(eCurve, t, nullptr, basePoint, s, context);
@@ -181,21 +190,20 @@ bool PIDGEN3::BINK2002::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *
EC_POINT_free(t);
// If the computed hash checks out, the key is valid.
- return compHash == pHash;
+ return compHash == Hash;
}
/* Generates a Windows Server 2003-like Product Key. */
-void PIDGEN3::BINK2002::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
- DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25])
+BOOL BINK2002::Generate(std::string &pKey)
{
BN_CTX *numContext = BN_CTX_new();
BIGNUM *c = BN_new(), *e = BN_new(), *s = BN_new(), *x = BN_new(), *y = BN_new();
- QWORD pRaw[2]{}, pSignature = 0;
+ QWORD pRaw[2]{};
// Data segment of the RPK.
- DWORD pData = pChannelID << 1 | pUpgrade;
+ DWORD pData = ChannelID << 1 | isUpgrade;
BOOL noSquare;
@@ -243,8 +251,8 @@ void PIDGEN3::BINK2002::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *
msgBuffer[0x04] = (pHash & 0x0000FF00) >> 8;
msgBuffer[0x05] = (pHash & 0x00FF0000) >> 16;
msgBuffer[0x06] = (pHash & 0xFF000000) >> 24;
- msgBuffer[0x07] = (pAuthInfo & 0x00FF);
- msgBuffer[0x08] = (pAuthInfo & 0xFF00) >> 8;
+ msgBuffer[0x07] = (AuthInfo & 0x00FF);
+ msgBuffer[0x08] = (AuthInfo & 0xFF00) >> 8;
msgBuffer[0x09] = 0x00;
msgBuffer[0x0A] = 0x00;
@@ -323,21 +331,21 @@ void PIDGEN3::BINK2002::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *
BN_rshift1(s, s);
// Translate resulting scalar into a 64-bit integer (the byte order is little-endian).
- BN_bn2lebinpad(s, (BYTE *)&pSignature, BN_num_bytes(s));
+ BN_bn2lebinpad(s, (BYTE *)&Signature, BN_num_bytes(s));
// Pack product key.
- Pack(pRaw, pUpgrade, pChannelID, pHash, pSignature, pAuthInfo);
+ Pack(pRaw);
fmt::print(UMSKT::debug, "Generation results:\n");
- fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
- fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", pChannelID);
- fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
- fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
- fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo);
+ fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", isUpgrade);
+ fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", ChannelID);
+ fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", Hash);
+ fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", Signature);
+ fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", AuthInfo);
fmt::print(UMSKT::debug, "\n");
EC_POINT_free(r);
- } while (pSignature > BITMASK(62) || noSquare);
+ } while (Signature > BITMASK(62) || noSquare);
// ↑ ↑ ↑
// The signature can't be longer than 62 bits, else it will
// overlap with the AuthInfo segment next to it.
@@ -352,4 +360,6 @@ void PIDGEN3::BINK2002::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *
BN_free(e);
BN_CTX_free(numContext);
+
+ return true;
}
diff --git a/src/libumskt/pidgen3/BINK2002.h b/src/libumskt/pidgen3/BINK2002.h
index 9391b87..8c7e677 100644
--- a/src/libumskt/pidgen3/BINK2002.h
+++ b/src/libumskt/pidgen3/BINK2002.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/6/2023
+ * @FileCreated by Neo on 06/06/2023
* @Maintainer Neo
*/
@@ -25,18 +25,14 @@
#include "PIDGEN3.h"
-EXPORT class PIDGEN3::BINK2002
+class BINK2002 : public PIDGEN3
{
+
public:
- static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
- DWORD &pAuthInfo);
-
- static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature, DWORD pAuthInfo);
-
- static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]);
-
- static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID,
- DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]);
+ BOOL Unpack(QWORD (&pRaw)[2]) override;
+ BOOL Pack(QWORD (&pRaw)[2]) override;
+ BOOL Verify(std::string &pKey) override;
+ BOOL Generate(std::string &pKey) override;
};
#endif // UMSKT_BINK2002_H
diff --git a/src/libumskt/pidgen3/PIDGEN3.cpp b/src/libumskt/pidgen3/PIDGEN3.cpp
new file mode 100644
index 0000000..9bf0a60
--- /dev/null
+++ b/src/libumskt/pidgen3/PIDGEN3.cpp
@@ -0,0 +1,258 @@
+/**
+ * This file is a part of the UMSKT Project
+ *
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ * @FileCreated by Andrew on 01/06/2023
+ * @Maintainer Andrew
+ */
+
+#include "PIDGEN3.h"
+
+/**
+ * https://xkcd.com/221/
+ *
+ * @return 4
+ */
+int getRandomNumber()
+{
+ return 4; // chosen by fair dice roll
+ // guaranteed to be random
+}
+
+/**
+ * Initializes the elliptic curve
+ *
+ * @param pSel [in] prime
+ * @param aSel [in] a
+ * @param bSel [in] b
+ * @param generatorXSel [in] G[x]
+ * @param generatorYSel [in] G[y]
+ * @param publicKeyXSel [in] pub[x]
+ * @param publicKeyYSel [in] pub[y]
+ * @param genOrderSel [in] computed order of G
+ * @param privateKeySel [in] computed private key
+ *
+ * @return true on success, false on fail
+ */
+BOOL PIDGEN3::LoadEllipticCurve(const std::string pSel, const std::string aSel, const std::string bSel,
+ const std::string generatorXSel, const std::string generatorYSel,
+ const std::string publicKeyXSel, const std::string publicKeyYSel,
+ const std::string genOrderSel, const std::string privateKeySel)
+{
+ // We cannot produce a valid key without knowing the private key k. The reason for this is that
+ // we need the result of the function K(x; y) = kG(x; y).
+
+ // We can, however, validate any given key using the available public key: {p, a, b, G, K}.
+ // genOrder the order of the generator G, a value we have to reverse -> Schoof's Algorithm.
+
+ // Initialize BIGNUM and BIGNUMCTX structures.
+ // BIGNUM - Large numbers
+ // BIGNUMCTX - Context large numbers (temporary)
+ BIGNUM *a, *b, *p, *generatorX, *generatorY, *publicKeyX, *publicKeyY;
+ BN_CTX *context;
+
+ // We're presented with an elliptic curve, a multivariable function y(x; p; a; b), where
+ // y^2 % p = x^3 + ax + b % p.
+ a = BN_new();
+ b = BN_new();
+ p = BN_new();
+
+ // Public key will consist of the resulting (x; y) values.
+ publicKeyX = BN_new();
+ publicKeyY = BN_new();
+
+ // G(x; y) is a generator function, its return value represents a point on the elliptic curve.
+ generatorX = BN_new();
+ generatorY = BN_new();
+
+ // Context variable
+ context = BN_CTX_new();
+
+ /* Public data */
+ BN_dec2bn(&p, pSel.c_str());
+ BN_dec2bn(&a, aSel.c_str());
+ BN_dec2bn(&b, bSel.c_str());
+ BN_dec2bn(&generatorX, generatorXSel.c_str());
+ BN_dec2bn(&generatorY, generatorYSel.c_str());
+
+ BN_dec2bn(&publicKeyX, publicKeyXSel.c_str());
+ BN_dec2bn(&publicKeyY, publicKeyYSel.c_str());
+
+ /* Computed Data */
+ BN_dec2bn(&genOrder, genOrderSel.c_str());
+ BN_dec2bn(&privateKey, privateKeySel.c_str());
+ BN_sub(privateKey, genOrder, privateKey);
+
+ /* Elliptic Curve calculations. */
+ // The group is defined via Fp = all integers [0; p - 1], where p is prime.
+ // The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the
+ // curve given in group.
+ 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).
+ genPoint = EC_POINT_new(eCurve);
+ EC_POINT_set_affine_coordinates(eCurve, genPoint, generatorX, generatorY, context);
+
+ // Create new point for the public key on the elliptic curve and set its coordinates to (pubX; pubY).
+ pubPoint = EC_POINT_new(eCurve);
+ EC_POINT_set_affine_coordinates(eCurve, pubPoint, publicKeyX, publicKeyY, context);
+
+ // If generator and public key points are not on the elliptic curve, either the generator or the public key values
+ // are incorrect.
+ assert(EC_POINT_is_on_curve(eCurve, genPoint, context) == true);
+ assert(EC_POINT_is_on_curve(eCurve, pubPoint, context) == true);
+
+ // Cleanup
+ BN_CTX_free(context);
+ BN_free(p);
+ BN_free(a);
+ BN_free(b);
+ BN_free(generatorX);
+ BN_free(generatorY);
+ BN_free(publicKeyX);
+ BN_free(publicKeyY);
+
+ return true;
+}
+
+/**
+ * Convert data between endianness types.
+ *
+ * @param data [in]
+ * @param length [in]
+ **/
+inline void PIDGEN3::endian(BYTE *data, int length)
+{
+ for (int i = 0; i < length / 2; i++)
+ {
+ BYTE temp = data[i];
+ data[i] = data[length - i - 1];
+ data[length - i - 1] = temp;
+ }
+}
+
+/**
+ * Converts an OpenSSL BigNumber to it's Little Endian binary equivalent
+ *
+ * @param a [in] BigNumber to convert
+ * @param to [out] char* binary representation
+ * @param tolen [in] length of the char* array
+ *
+ * @return length of number in to
+ **/
+int PIDGEN3::BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen)
+{
+ if (a == nullptr || to == nullptr)
+ {
+ return 0;
+ }
+
+ int len = BN_bn2bin(a, to);
+
+ if (len > tolen)
+ {
+ return -1;
+ }
+
+ // Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen.
+ endian(to, tolen);
+
+ return len;
+}
+
+/**
+ * Converts from byte sequence to the CD-key.
+ *
+ * @param cdKey [out] std::string CDKey input
+ * @param byteSeq [in] BYTE*
+ **/
+void PIDGEN3::base24(std::string &cdKey, BYTE *byteSeq)
+{
+ BYTE rbyteSeq[16];
+ BIGNUM *z;
+
+ // Copy byte sequence to the reversed byte sequence.
+ memcpy(rbyteSeq, byteSeq, sizeof(rbyteSeq));
+
+ // Skip trailing zeroes and reverse y.
+ int length;
+
+ for (length = 15; rbyteSeq[length] <= 0; length--)
+ {
+ ; // do nothing, just counting
+ }
+
+ endian(rbyteSeq, ++length);
+
+ // Convert reversed byte sequence to BigNum z.
+ z = BN_bin2bn(rbyteSeq, length, nullptr);
+
+ // Divide z by 24 and convert the remainder to a CD-key char.
+ for (int i = 24; i >= 0; i--)
+ {
+ cdKey[i] = pKeyCharset[BN_div_word(z, 24)];
+ }
+
+ BN_free(z);
+}
+
+/**
+ * Converts from CD-key to a byte sequence.
+ *
+ * @param byteSeq [out] *BYTE representation of the CDKey
+ * @param cdKey [in] std::string CDKey to convert
+ **/
+void PIDGEN3::unbase24(BYTE *byteSeq, std::string cdKey)
+{
+ BYTE pDecodedKey[PK_LENGTH + NULL_TERMINATOR]{};
+ BIGNUM *y = BN_new();
+
+ BN_zero(y);
+
+ // Remove dashes from the CD-key and put it into a Base24 byte array.
+ for (int i = 0, k = 0; i < cdKey.length() && k < PK_LENGTH; i++)
+ {
+ for (int j = 0; j < 24; j++)
+ {
+ if (cdKey[i] != '-' && cdKey[i] == pKeyCharset[j])
+ {
+ pDecodedKey[k++] = j;
+ break;
+ }
+ }
+ }
+
+ // Empty byte sequence.
+ memset(byteSeq, 0, 16);
+
+ // Calculate the weighed sum of byte array elements.
+ for (int i = 0; i < PK_LENGTH; i++)
+ {
+ BN_mul_word(y, PK_LENGTH - 1);
+ BN_add_word(y, pDecodedKey[i]);
+ }
+
+ // Acquire length.
+ int n = BN_num_bytes(y);
+
+ // Place the generated code into the byte sequence.
+ BN_bn2bin(y, byteSeq);
+ BN_free(y);
+
+ // Reverse the byte sequence.
+ endian(byteSeq, n);
+}
diff --git a/src/libumskt/pidgen3/PIDGEN3.h b/src/libumskt/pidgen3/PIDGEN3.h
index e396c47..272ba22 100644
--- a/src/libumskt/pidgen3/PIDGEN3.h
+++ b/src/libumskt/pidgen3/PIDGEN3.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/24/2023
+ * @FileCreated by Neo on 06/24/2023
* @Maintainer Neo
*/
@@ -27,23 +27,65 @@
class PIDGEN3
{
+ protected:
+ EC_GROUP *eCurve;
+ EC_POINT *basePoint, *publicKey, *genPoint, *pubPoint;
+ BIGNUM *genOrder, *privateKey;
+ DWORD Serial, AuthInfo, ChannelID, Hash;
+ QWORD Signature;
+ BOOL isUpgrade;
+
public:
- class BINK1998;
- class BINK2002;
+ PIDGEN3()
+ {
+ }
- // 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 void endian(BYTE *data, int length);
- static EC_GROUP *initializeEllipticCurve(std::string pSel, std::string aSel, std::string bSel,
- std::string generatorXSel, std::string generatorYSel,
- std::string publicKeyXSel, std::string publicKeyYSel, EC_POINT *&genPoint,
- EC_POINT *&pubPoint);
+ ~PIDGEN3()
+ {
+ EC_GROUP_free(eCurve);
+ EC_POINT_free(genPoint);
+ EC_POINT_free(pubPoint);
+ EC_POINT_free(basePoint);
+ EC_POINT_free(publicKey);
+ BN_free(genOrder);
+ BN_free(privateKey);
+ BN_free(privateKey);
+ BN_free(genOrder);
+ }
- // key.cpp
static constexpr char pKeyCharset[] = "BCDFGHJKMPQRTVWXY2346789";
- static void unbase24(BYTE *byteSeq, const char *cdKey);
- static void base24(char *cdKey, BYTE *byteSeq);
+
+ BOOL LoadEllipticCurve(std::string pSel, std::string aSel, std::string bSel, std::string generatorXSel,
+ std::string generatorYSel, std::string publicKeyXSel, std::string publicKeyYSel,
+ std::string genOrderSel, std::string privateKeySel);
+
+ virtual BOOL Unpack(QWORD (&pRaw)[2]) = 0;
+ virtual BOOL Pack(QWORD (&pRaw)[2]) = 0;
+ virtual BOOL Verify(std::string &pKey) = 0;
+ virtual BOOL Generate(std::string &pKey) = 0;
+
+ // PIDGEN3.cpp
+ // Hello OpenSSL developers, please tell me, where is this function at?
+ int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen);
+ void endian(BYTE *data, int length);
+
+ void base24(std::string &cdKey, BYTE *byteSeq);
+ void unbase24(BYTE *byteSeq, std::string cdKey);
+
+ void setSerial(DWORD serialIn)
+ {
+ Serial = serialIn;
+ }
+
+ void setAuthInfo(DWORD AuthInfoIn)
+ {
+ AuthInfo = AuthInfoIn;
+ }
+
+ void setChannelID(DWORD ChannelIDIn)
+ {
+ ChannelID = ChannelIDIn;
+ }
};
#endif // UMSKT_PIDGEN3_H
diff --git a/src/libumskt/pidgen3/key.cpp b/src/libumskt/pidgen3/key.cpp
deleted file mode 100644
index 7cb2a8a..0000000
--- a/src/libumskt/pidgen3/key.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * This file is a part of the UMSKT Project
- *
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
-
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
- * @FileCreated by Neo on 5/26/2023
- * @Maintainer Andrew
- */
-
-#include "PIDGEN3.h"
-
-/* Converts from CD-key to a byte sequence. */
-void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey)
-{
- BYTE pDecodedKey[PK_LENGTH + NULL_TERMINATOR]{};
- BIGNUM *y = BN_new();
-
- BN_zero(y);
-
- // Remove dashes from the CD-key and put it into a Base24 byte array.
- for (int i = 0, k = 0; i < strlen(cdKey) && k < PK_LENGTH; i++)
- {
- for (int j = 0; j < 24; j++)
- {
- if (cdKey[i] != '-' && cdKey[i] == pKeyCharset[j])
- {
- pDecodedKey[k++] = j;
- break;
- }
- }
- }
-
- // Empty byte sequence.
- memset(byteSeq, 0, 16);
-
- // Calculate the weighed sum of byte array elements.
- for (int i = 0; i < PK_LENGTH; i++)
- {
- BN_mul_word(y, PK_LENGTH - 1);
- BN_add_word(y, pDecodedKey[i]);
- }
-
- // Acquire length.
- int n = BN_num_bytes(y);
-
- // Place the generated code into the byte sequence.
- BN_bn2bin(y, byteSeq);
- BN_free(y);
-
- // Reverse the byte sequence.
- endian(byteSeq, n);
-}
-
-/* Converts from byte sequence to the CD-key. */
-void PIDGEN3::base24(char *cdKey, BYTE *byteSeq)
-{
- BYTE rbyteSeq[16];
- BIGNUM *z;
-
- // Copy byte sequence to the reversed byte sequence.
- memcpy(rbyteSeq, byteSeq, sizeof(rbyteSeq));
-
- // Skip trailing zeroes and reverse y.
- int length;
-
- for (length = 15; rbyteSeq[length] == 0; length--)
- {
- ;
- }
- endian(rbyteSeq, ++length);
-
- // Convert reversed byte sequence to BigNum z.
- z = BN_bin2bn(rbyteSeq, length, nullptr);
-
- // Divide z by 24 and convert the remainder to a CD-key char.
- cdKey[25] = 0;
-
- for (int i = 24; i >= 0; i--)
- {
- cdKey[i] = pKeyCharset[BN_div_word(z, 24)];
- }
-
- BN_free(z);
-}
diff --git a/src/libumskt/pidgen3/util.cpp b/src/libumskt/pidgen3/util.cpp
deleted file mode 100644
index 38b81a4..0000000
--- a/src/libumskt/pidgen3/util.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * This file is a part of the UMSKT Project
- *
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
-
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
- * @FileCreated by Andrew on 01/06/2023
- * @Maintainer Andrew
- */
-
-#include "PIDGEN3.h"
-
-int randomRange()
-{
- return 4; // chosen by fair dice roll
- // guaranteed to be random
-}
-
-/* Convert data between endianness types. */
-void PIDGEN3::endian(BYTE *data, int length)
-{
- for (int i = 0; i < length / 2; i++)
- {
- BYTE temp = data[i];
- data[i] = data[length - i - 1];
- data[length - i - 1] = temp;
- }
-}
-
-/* Initializes the elliptic curve. */
-EC_GROUP *PIDGEN3::initializeEllipticCurve(const std::string pSel, const std::string aSel, const std::string bSel,
- const std::string generatorXSel, const std::string generatorYSel,
- const std::string publicKeyXSel, const std::string publicKeyYSel,
- EC_POINT *&genPoint, EC_POINT *&pubPoint)
-{
- // Initialize BIGNUM and BIGNUMCTX structures.
- // BIGNUM - Large numbers
- // BIGNUMCTX - Context large numbers (temporary)
- BIGNUM *a, *b, *p, *generatorX, *generatorY, *publicKeyX, *publicKeyY;
- BN_CTX *context;
-
- // We're presented with an elliptic curve, a multivariable function y(x; p; a; b), where
- // y^2 % p = x^3 + ax + b % p.
- a = BN_new();
- b = BN_new();
- p = BN_new();
-
- // Public key will consist of the resulting (x; y) values.
- publicKeyX = BN_new();
- publicKeyY = BN_new();
-
- // G(x; y) is a generator function, its return value represents a point on the elliptic curve.
- generatorX = BN_new();
- generatorY = BN_new();
-
- // Context variable
- context = BN_CTX_new();
-
- /* Public data */
- BN_dec2bn(&p, pSel.c_str());
- BN_dec2bn(&a, aSel.c_str());
- BN_dec2bn(&b, bSel.c_str());
- BN_dec2bn(&generatorX, generatorXSel.c_str());
- BN_dec2bn(&generatorY, generatorYSel.c_str());
-
- BN_dec2bn(&publicKeyX, publicKeyXSel.c_str());
- BN_dec2bn(&publicKeyY, publicKeyYSel.c_str());
-
- /* Elliptic Curve calculations. */
- // The group is defined via Fp = all integers [0; p - 1], where p is prime.
- // The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the
- // curve given in group.
- 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).
- genPoint = EC_POINT_new(eCurve);
- EC_POINT_set_affine_coordinates(eCurve, genPoint, generatorX, generatorY, context);
-
- // Create new point for the public key on the elliptic curve and set its coordinates to (pubX; pubY).
- pubPoint = EC_POINT_new(eCurve);
- EC_POINT_set_affine_coordinates(eCurve, pubPoint, publicKeyX, publicKeyY, context);
-
- // If generator and public key points are not on the elliptic curve, either the generator or the public key values
- // are incorrect.
- assert(EC_POINT_is_on_curve(eCurve, genPoint, context) == true);
- assert(EC_POINT_is_on_curve(eCurve, pubPoint, context) == true);
-
- // Cleanup
- BN_CTX_free(context);
- BN_free(p);
- BN_free(a);
- BN_free(b);
- BN_free(generatorX);
- BN_free(generatorY);
- BN_free(publicKeyX);
- BN_free(publicKeyY);
-
- return eCurve;
-}
-
-int PIDGEN3::BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen)
-{
- if (a == nullptr || to == nullptr)
- {
- return 0;
- }
-
- int len = BN_bn2bin(a, to);
-
- if (len > tolen)
- {
- return -1;
- }
-
- // Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen.
- endian(to, tolen);
-
- return len;
-}
diff --git a/src/main.cpp b/src/main.cpp
index f3571c4..c85ea8f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -21,47 +21,15 @@
*/
#include "cli.h"
-#include "header.h"
-
-Options options;
int main(int argc, char *argv[])
{
- if (!CLI::parseCommandLine(argc, argv, &options))
- {
- fmt::print("error parsing command line options\n");
- CLI::showHelp(argv);
- return !options.error ? 0 : 1;
- }
-
- json keys;
-
- int status = CLI::validateCommandLine(&options, argv, &keys);
- if (status > 0)
+ int status;
+ if (status = CLI::Init(argc, argv); status > 0)
{
return status;
}
- CLI run(options, keys);
-
- switch (options.applicationMode)
- {
- case MODE_BINK1998_GENERATE:
- return run.BINK1998Generate();
-
- case MODE_BINK2002_GENERATE:
- return run.BINK2002Generate();
-
- case MODE_BINK1998_VALIDATE:
- return run.BINK1998Validate();
-
- case MODE_BINK2002_VALIDATE:
- return run.BINK2002Validate();
-
- case MODE_CONFIRMATION_ID:
- return run.ConfirmationID();
-
- default:
- return 1;
- }
+ auto cli = CLI();
+ return cli.Run();
}
diff --git a/src/options.cpp b/src/options.cpp
new file mode 100644
index 0000000..b7cd67e
--- /dev/null
+++ b/src/options.cpp
@@ -0,0 +1,318 @@
+/**
+ * This file is a part of the UMSKT Project
+ *
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ * @FileCreated by Neo on 01/02/2024
+ * @Maintainer Neo
+ */
+
+#include "cli.h"
+
+// define static storage
+std::array CLI::helpOptions;
+
+void CLI::SetHelpText()
+{
+ helpOptions[OPTION_HELP] = {"h", "help", "show this help text", false, "", &DisplayHelp};
+
+ helpOptions[OPTION_VERBOSE] = {"v", "verbose", "enable verbose output", false, "", &SetVerboseOption};
+
+ helpOptions[OPTION_DEBUG] = {"d", "debug", "enable debug output", false, "", &SetDebugOption};
+
+ helpOptions[OPTION_FILE] = {"f", "file", "specify which keys file to load", true, "", &SetFileOption};
+
+ helpOptions[OPTION_LIST] = {"l", "list", "list supported products", false, "", &SetListOption};
+
+ helpOptions[OPTION_NUMBER] = {"n", "number", "(PIDGEN only) number of keys to generate",
+ true, "1", &SetNumberOption};
+
+ helpOptions[OPTION_PRODUCT] = {"p", "product", "which product to generate keys for",
+ true, options.productCode, nullptr};
+
+ helpOptions[OPTION_ACTIVATIONID] = {
+ "i", "instid", "(activation only) installation ID used to generate confirmation ID",
+ true, "", &SetActivationIDOption};
+
+ helpOptions[OPTION_ACTIVATIONPID] = {
+ "P", "productid", "(Office activation only) product ID to generate confirmation ID for",
+ true, "", &SetProductIDOption};
+
+ helpOptions[OPTION_OEM] = {"o", "oem", "\t(PIDGEN) generate an OEM key", false, "", &SetOEMOption};
+
+ helpOptions[OPTION_UPGRADE] = {"u", "upgrade", "(PIDGEN 3 only) generate an upgrade key",
+ false, "", &SetUpgradeOption};
+
+ helpOptions[OPTION_BINK] = {"b", "binkid", "(advanced) override which BINK identifier to load",
+ true, "", &SetBINKOption};
+
+ helpOptions[OPTION_CHANNELID] = {"c", "channelid", "(advanced) override which product channel to use",
+ true, "", &SetChannelIDOption};
+
+ helpOptions[OPTION_SERIAL] = {
+ "s", "serial", "(advanced, PIDGEN 2/3 [BINK 1998] only) specify a serial to generate",
+ true, "", &SetSerialOption};
+
+ helpOptions[OPTION_AUTHDATA] = {
+ "a", "authdata", "(advanced, PIDGEN 3 [BINK 2000] only) specify a value for the authentication data field",
+ true, "", nullptr};
+
+ helpOptions[OPTION_VALIDATE] = {
+ "V", "validate", "validate a specified product ID against known BINKs and algorithms",
+ true, "", &SetValidateOption};
+}
+
+/**
+ *
+ * @return success
+ */
+BOOL CLI::parseCommandLine()
+{
+ for (DWORD i = 1; i < options.argc; i++)
+ {
+ std::string arg = options.argv[i];
+
+ if (arg[0] == '-')
+ {
+ arg.erase(0, 1);
+ }
+ if (arg[0] == '-')
+ {
+ arg.erase(0, 1);
+ }
+
+ if (arg.empty())
+ {
+ continue;
+ }
+
+ for (BYTE j = 0; j < CLIHelpOptionID_END; j++)
+ {
+ if (arg != helpOptions[j].Short && arg != helpOptions[j].Long)
+ {
+ continue;
+ }
+
+ std::string nextarg;
+ if (helpOptions[j].hasArguments)
+ {
+ if (i == options.argc - 1)
+ {
+ options.error = true;
+ goto CommandLineParseEnd;
+ }
+ else
+ {
+ nextarg = arg[i + 1];
+ }
+ }
+
+ auto success = helpOptions[j].handler(1, &nextarg[0]);
+
+ if (!success)
+ {
+ options.error = true;
+ goto CommandLineParseEnd;
+ }
+ if (options.help)
+ {
+ goto CommandLineParseEnd;
+ }
+ goto ParseNextCommandLineOption;
+ }
+
+ fmt::print("unknown option: {}\n", arg);
+ options.error = true;
+ goto CommandLineParseEnd;
+
+ ParseNextCommandLineOption:
+ continue;
+ }
+
+CommandLineParseEnd:
+ if (options.error)
+ {
+ DisplayErrorMessage(0, nullptr);
+ }
+ return !options.error;
+}
+
+/**
+ *
+ * @return success
+ */
+BOOL CLI::DisplayHelp(int, char *)
+{
+ options.help = true;
+ fmt::print("usage: {} \n", options.argv[0]);
+
+ for (BYTE i = 0; i < CLIHelpOptionID_END; i++)
+ {
+ CLIHelpOptions o = helpOptions[i];
+ fmt::print(" -{} --{}\t{}", o.Short, o.Long, o.HelpText);
+ if (!o.Default.empty())
+ {
+ fmt::print(" (defaults to {})", o.Default);
+ }
+ fmt::print("\n");
+ }
+
+ fmt::print("\n");
+
+ return true;
+}
+
+BOOL CLI::DisplayErrorMessage(int, char *)
+{
+ fmt::print("error parsing command line options\n");
+ DisplayHelp(0, nullptr);
+ options.error = true;
+ return false;
+}
+
+BOOL CLI::SetVerboseOption(int, char *)
+{
+ fmt::print("enabling verbose option\n");
+ options.verbose = true;
+ UMSKT::VERBOSE = true;
+ UMSKT::setDebugOutput(stderr);
+ return true;
+}
+
+BOOL CLI::SetDebugOption(int, char *)
+{
+ fmt::print("enabling debug option\n");
+ options.verbose = true;
+ UMSKT::DEBUG = true;
+ UMSKT::setDebugOutput(stderr);
+ return true;
+}
+
+BOOL CLI::SetListOption(int, char *)
+{
+ options.list = true;
+ return true;
+}
+
+BOOL CLI::SetOEMOption(int, char *)
+{
+ options.oem = true;
+ return true;
+}
+
+BOOL CLI::SetUpgradeOption(int, char *)
+{
+ options.upgrade = true;
+ return true;
+}
+
+BOOL CLI::SetFileOption(int count, char *file)
+{
+ options.keysFilename = file;
+ return true;
+}
+
+BOOL CLI::SetNumberOption(int count, char *num)
+{
+ int nKeys;
+ if (!sscanf(num, "%d", &nKeys))
+ {
+ return false;
+ }
+
+ options.numKeys = nKeys;
+ return true;
+}
+
+/**
+ *
+ * @param count
+ * @param channum
+ * @return
+ */
+BOOL CLI::SetChannelIDOption(int count, char *channum)
+{
+ int siteID;
+ if (!sscanf(channum, "%d", &siteID))
+ {
+ return false;
+ }
+
+ // channel ids must be between 000 and 999
+ if (siteID > 999)
+ {
+ fmt::print("ERROR: refusing to create a key with a Channel ID greater than 999\n");
+ return false;
+ }
+
+ options.channelID = siteID;
+ return true;
+}
+
+BOOL CLI::SetBINKOption(int count, char *bink)
+{
+ options.binkid = bink;
+ return true;
+}
+
+/**
+ *
+ * @param count
+ * @param arg
+ * @return
+ */
+BOOL CLI::SetSerialOption(int count, char *arg)
+{
+ int serial_val;
+ if (!sscanf(arg, "%d", &serial_val))
+ {
+ return false;
+ }
+
+ // serials must be between 000000 and 999999
+ if (serial_val > 999999)
+ {
+ fmt::print("ERROR: refusing to create a key with a Serial not between 000000 and 999999\n");
+ return false;
+ }
+
+ options.serialSet = true;
+ options.serial = serial_val;
+ return true;
+}
+
+BOOL CLI::SetActivationIDOption(int count, char *aid)
+{
+ options.instid = aid;
+ options.state = STATE_CONFIRMATION_ID;
+ return true;
+}
+
+BOOL CLI::SetProductIDOption(int count, char *product)
+{
+ if (options.verbose)
+ {
+ fmt::print("Setting product ID to {}", product);
+ }
+ options.productid = product;
+ return true;
+}
+
+BOOL CLI::SetValidateOption(int count, char *product)
+{
+ options.keyToCheck = product;
+ return true;
+}
diff --git a/src/header.h b/src/options.h
similarity index 50%
rename from src/header.h
rename to src/options.h
index 3ef7e48..a64743a 100644
--- a/src/header.h
+++ b/src/options.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,26 +16,45 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 5/26/2023
+ * @FileCreated by Neo on 01/02/2024
* @Maintainer Neo
*/
-#ifndef UMSKT_HEADER_H
-#define UMSKT_HEADER_H
+#ifndef UMSKT_OPTIONS_H
+#define UMSKT_OPTIONS_H
-#include "typedefs.h"
+typedef BOOL CLIHandlerFunc(int, char *);
-#include
-#include
-#include
-#include
-#include
-#include
+enum CLIHelpOptionIDs
+{
+ OPTION_HELP,
+ OPTION_VERBOSE,
+ OPTION_DEBUG,
+ OPTION_FILE,
+ OPTION_LIST,
+ OPTION_NUMBER,
+ OPTION_PRODUCT,
+ OPTION_OEM,
+ OPTION_UPGRADE,
+ OPTION_ACTIVATIONID,
+ OPTION_ACTIVATIONPID,
+ OPTION_BINK,
+ OPTION_CHANNELID,
+ OPTION_SERIAL,
+ OPTION_AUTHDATA,
+ OPTION_VALIDATE,
-#include
-#include
+ CLIHelpOptionID_END
+};
-using json = nlohmann::json;
-namespace fs = std::filesystem;
+struct CLIHelpOptions
+{
+ std::string Short;
+ std::string Long;
+ std::string HelpText;
+ BOOL hasArguments;
+ std::string Default;
+ CLIHandlerFunc *handler;
+};
-#endif // UMSKT_HEADER_H
+#endif // UMSKT_OPTIONS_H
diff --git a/src/typedefs.h b/src/typedefs.h
index 3adf14d..6e6f7d0 100644
--- a/src/typedefs.h
+++ b/src/typedefs.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/24/2023
+ * @FileCreated by Neo on 06/24/2023
* @Maintainer Neo
*/
@@ -29,13 +29,19 @@
#ifdef DEBUG
#include
#else
-#define assert(x) /* nothing */
+#define assert(x) /* do nothing */
#endif
#ifdef _MSC_VER
#define EXPORT extern "C" __declspec(dllexport)
+#define INLINE __forceinline
+#elif defined(__GNUC__)
+#define EXPORT extern "C" __attribute__((visibility("default")))
+#define INLINE __attribute__((always_inline))
#else
#define EXPORT extern "C"
+#define INLINE
+#warning "function inlining not handled"
#endif
#ifdef __EMSCRIPTEN__
@@ -45,6 +51,21 @@
#define FNEXPORT EXPORT
#endif
+#ifdef _MSC_VER
+#ifndef strncasecmp
+#define strncasecmp _strnicmp
+#endif
+#ifndef strcasecmp
+#define strcasecmp _stricmp
+#endif
+#ifndef strcmp
+#define strcmp strcmp_s
+#endif
+#ifndef sscanf
+#define sscanf sscanf_s
+#endif
+#endif
+
// Type definitions
typedef bool BOOL;
typedef uint8_t BYTE;
@@ -56,4 +77,12 @@ typedef uint64_t QWORD;
typedef unsigned __int128 OWORD;
#endif
+typedef union {
+ // OWORD oword;
+ QWORD qword[2];
+ DWORD dword[4];
+ WORD word[8];
+ BYTE byte[16];
+} Q_OWORD;
+
#endif // UMSKT_TYPEDEFS_H
diff --git a/src/windows/dllmain.cpp b/src/windows/dllmain.cpp
index e769ebd..179103e 100644
--- a/src/windows/dllmain.cpp
+++ b/src/windows/dllmain.cpp
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
diff --git a/src/windows/resource.h b/src/windows/resource.h
index af03788..133a7ef 100644
--- a/src/windows/resource.h
+++ b/src/windows/resource.h
@@ -1,7 +1,7 @@
/**
* This file is a part of the UMSKT Project
*
- * Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
+ * Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
- * @FileCreated by Neo on 6/17/2023
+ * @FileCreated by Neo on 06/17/2023
* @Maintainer Neo
*/
diff --git a/src/windows/umskt.rc b/src/windows/umskt.rc
index df98e3002919733ef2d48bb3488224acb0265b71..7ff8bd6b4492a0ea2eb4676167b6f4deb73f472e 100644
GIT binary patch
delta 19
bcmeyM_DOBRJVuj^^N+JK8f;Ew1prBU2IT+%