diff --git a/.github/workflows/dos-djgpp.yml b/.github/workflows/dos-djgpp.yml index f2f6c9f..d28d938 100644 --- a/.github/workflows/dos-djgpp.yml +++ b/.github/workflows/dos-djgpp.yml @@ -27,26 +27,26 @@ on: workflow_dispatch: env: - CMAKE_C_COMPILER: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-gcc - CMAKE_CXX_COMPILER: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-g++ + CC: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-gcc + CXX: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-g++ CMAKE_FIND_ROOT_PATH: ${{ github.workspace }}/djgpp - CMAKE_FIND_ROOT_PATH_MODE_PROGRAM: NEVER - CMAKE_FIND_ROOT_PATH_MODE_LIBRARY: ONLY - CMAKE_FIND_ROOT_PATH_MODE_INCLUDE: ONLY - CMAKE_FIND_ROOT_PATH_MODE_PACKAGE: ONLY WATT_ROOT: ${{ github.workspace }}/djgpp/watt32 jobs: build: runs-on: ubuntu-latest steps: + - name: Checkout Source Tree + uses: actions/checkout@v3 + - name: Setup build environment run: | sudo apt -y update - sudo apt -y install build-essential cmake wget 7zip git flex nasm libslang2-dev pkg-config libslang2-modules gcc-multilib + sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib - name: Download and Setup DJGPP Toolchain run: | + pushd ${{ github.workspace }} wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2 tar xjf djgpp-linux64-gcc1220.tar.bz2 cd ${{ github.workspace }}/djgpp @@ -54,40 +54,34 @@ jobs: cd watt32/util make clean && make linux cd ../src + source ${{ github.workspace }}/djgpp/setenv ./configur.sh djgpp make -f djgpp.mak - ln -s ${{ github.workspace }}/djgpp/watt32/lib/libwatt.a ${{ github.workspace }}/djgpp/lib + ln -s ${WATT_ROOT}/lib/libwatt.a ${{ github.workspace }}/djgpp/lib - - name: Checkout and Cross Compile OpenSSL 3.1 + - name: Checkout and Cross Compile OpenSSL 3.1.2 run: | git clone https://github.com/UMSKT/openssl.git openssl pushd openssl - git checkout openssl-3.1.1 source ${{ github.workspace }}/djgpp/setenv ./Configure no-threads -DOPENSSL_DEV_NO_ATOMICS --prefix=${{ github.workspace }}/djgpp DJGPP make && make install popd - ls ${{ github.workspace }}/djgpp/i586-pc-msdosdjgpp/bin/ - - - name: Checkout Source Tree - uses: actions/checkout@v3 - name: Build - uses: threeal/cmake-action@v1.2.0 - with: - c-compiler: gcc - cxx-compiler: g++ - options: OPENSSL_ROOT_DIR:string=${{ github.workspace }}/djgpp DJGPP_WATT32=ON - run-build: true - - - name: Test & Move files to correct directory run: | - mkdir -p build/actions_upload - mv build/umskt build/actions_upload/umskt + source ${{ github.workspace }}/djgpp/setenv + pushd build + cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} + make + + - name: Move executable to upload directory + run: | + mkdir build/actions_upload + mv build/umskt.exe build/actions_upload/ - name: Upload build artifact uses: actions/upload-artifact@v3.1.2 with: - name: UMSKT-DOS-DJGPP + name: UMSKT-DOS path: build/actions_upload - diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 4c0e1e6..bcc2d23 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -1,61 +1,61 @@ -# 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 - -name: C/C++ CI (FreeBSD) - +# 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 + + name: C/C++ CI (FreeBSD) + on: push: branches: [ "*" ] paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip workflow_dispatch: - -jobs: - build: - runs-on: macos-12 - name: build-x86_64 - steps: - - uses: actions/checkout@v3 - - - name: Build & Test in FreeBSD - id: test - uses: vmactions/freebsd-vm@v0 - with: - envs: 'MYTOKEN MYTOKEN2' - usesh: true - prepare: | - pkg install -y cmake openssl git bash - - run: | - mkdir build - cd build - cmake .. - make - ./umskt # Execute the test here - - - name: Move files to correct directory - run: | - mkdir -p build/actions_upload - mv build/umskt build/actions_upload/umskt - - - name: Upload build artifact - uses: actions/upload-artifact@v3.1.2 - with: - name: UMSKT-FreeBSD - path: build/actions_upload + + jobs: + build: + runs-on: macos-latest + name: build-x86_64 + steps: + - uses: actions/checkout@v3 + + - name: Build & Test in FreeBSD + id: test + uses: vmactions/freebsd-vm@v0 + with: + envs: 'MYTOKEN MYTOKEN2' + usesh: true + prepare: | + pkg install -y cmake openssl git bash + + run: | + mkdir build + cd build + cmake .. + make + ./umskt # Execute the test here + + - name: Move files to correct directory + run: | + mkdir -p build/actions_upload + mv build/umskt build/actions_upload/umskt + + - name: Upload build artifact + uses: actions/upload-artifact@v3.1.2 + with: + name: UMSKT-FreeBSD + path: build/actions_upload diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 34e47c7..74a3d68 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -53,13 +53,8 @@ jobs: cd build/actions_upload ./umskt - - name: Zip artifact - run: | - cd build/actions_upload - zip -r UMSKT-macOS-${{ matrix.arch }}-static.zip umskt - - name: Upload build artifact uses: actions/upload-artifact@v3.1.2 with: - name: UMSKT-macOS-${{ matrix.arch }}-static + name: UMSKT-macOS-${{ matrix.arch }} path: build/actions_upload diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b1673de..50c6cd8 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -30,10 +30,27 @@ jobs: build-32bit: runs-on: windows-latest steps: - - name: Install v141_xp - uses: thepwrtank18/install-vs-components@v1.0.0 - with: - components: Microsoft.VisualStudio.Component.WinXP + # https://github.com/actions/runner-images/issues/6067#issuecomment-1213069040 + - name: Install Windows XP Support for Visual Studio + run: | + Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\" + $InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" + $componentsToAdd = @( + "Microsoft.VisualStudio.Component.WinXP" + ) + [string]$workloadArgs = $componentsToAdd | ForEach-Object {" --add " + $_} + $Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"",$workloadArgs, '--quiet', '--norestart', '--nocache') + $process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden + if ($process.ExitCode -eq 0) + { + Write-Host "components have been successfully added" + Get-ChildItem C:\ProgramData\Microsoft\VisualStudio\Packages\Microsoft.Windows.XPSupport.* + } + else + { + Write-Host "components were not installed" + exit 1 + } - name: Download And Install 32-bit OpenSSL 3.1.2 run: | @@ -57,14 +74,13 @@ jobs: - name: Configure UMSKT uses: threeal/cmake-action@v1.2.0 with: - working-directory: build generator: "Visual Studio 17 2022" options: CMAKE_SYSTEM_VERSION="5.1.2600" args: -A "Win32" -T v141_xp - name: Build UMSKT working-directory: build - run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release /P:XPDeprecationWarning=false + run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release - name: Upload build artifact uses: actions/upload-artifact@v3.1.2 @@ -75,11 +91,27 @@ jobs: build-64bit: runs-on: windows-latest steps: - - name: Install v141_xp - uses: thepwrtank18/install-vs-components@v1.0.0 - with: - components: Microsoft.VisualStudio.Component.WinXP - + - name: Install Windows XP Support for Visual Studio + run: | + Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\" + $InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" + $componentsToAdd = @( + "Microsoft.VisualStudio.Component.WinXP" + ) + [string]$workloadArgs = $componentsToAdd | ForEach-Object {" --add " + $_} + $Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"",$workloadArgs, '--quiet', '--norestart', '--nocache') + $process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden + if ($process.ExitCode -eq 0) + { + Write-Host "components have been successfully added" + Get-ChildItem C:\ProgramData\Microsoft\VisualStudio\Packages\Microsoft.Windows.XPSupport.* + } + else + { + Write-Host "components were not installed" + exit 1 + } + - name: Download And Install 64-bit OpenSSL 3.1.2 run: | $installDir = "$Env:ProgramFiles\OpenSSL" @@ -103,11 +135,11 @@ jobs: uses: threeal/cmake-action@v1.2.0 with: generator: "Visual Studio 17 2022" - args: -A "x64" -T v141_xp + args: -A "x64" -T "v141_xp" - name: Build UMSKT working-directory: build - run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release /P:XPDeprecationWarning=false + run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release - name: Upload build artifact uses: actions/upload-artifact@v3.1.2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c80a12..48bcae7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,92 +18,177 @@ # @FileCreated by Andrew on 05/30/2023 # @Maintainer Neo -cmake_minimum_required(VERSION 3.12) +CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +PROJECT(UMSKT) +SET(CMAKE_CXX_STANDARD 17) +SET(CMAKE_POSITION_INDEPENDENT_CODE ON) +SET(CMAKE_OSX_SYSROOT "macosx" CACHE PATH "macOS SDK path") +OPTION(UMSKT_USE_SHARED_OPENSSL "Force linking against the system-wide OpenSSL library" OFF) +OPTION(MUSL_STATIC "Enable fully static builds in a muslc environment (i.e. Alpine Linux)" OFF) +OPTION(DJGPP_WATT32 "Enable compilation and linking with DJGPP/WATT32/OpenSSL" OFF) +OPTION(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF) -project(UMSKT) -set(CMAKE_OSX_SYSROOT "macosx" CACHE PATH "macOS SDK path") +SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS}) +SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS}) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -option(UMSKT_USE_SHARED_OPENSSL "Force linking against the system-wide OpenSSL library" OFF) -option(MUSL_STATIC "Enable fully static builds in a muslc environment (i.e. Alpine Linux)" OFF) -option(DJGPP_WATT32 "Enable compilation and linking with DJGPP/WATT32/OpenSSL" OFF) -option(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF) - -find_package(OpenSSL REQUIRED) - -if(NOT OpenSSL_FOUND) - message(FATAL_ERROR "OpenSSL Development Libraries Not Found. Please install the required OpenSSL development package.") +# macOS does not support static build +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(UMSKT_USE_SHARED_OPENSSL ON) endif() -if(UMSKT_USE_SHARED_OPENSSL) - set(OPENSSL_USE_STATIC_LIBS FALSE) - set(OPENSSL_MSVC_STATIC_RT FALSE) -else() - set(OPENSSL_USE_STATIC_LIBS TRUE) - set(OPENSSL_MSVC_STATIC_RT TRUE) +IF(UMSKT_USE_SHARED_OPENSSL) + SET(OPENSSL_USE_STATIC_LIBS FALSE) + SET(OPENSSL_MSVC_STATIC_RT FALSE) + MESSAGE(WARNING "[UMSKT] Forcing shared OpenSSL runtime") +ELSE() + SET(OPENSSL_USE_STATIC_LIBS TRUE) + SET(OPENSSL_MSVC_STATIC_RT TRUE) +ENDIF() + + + +IF(DJGPP_WATT32) + SET(CMAKE_SYSTEM_NAME MSDOS) + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + 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() + +# find the system installed OpenSSL development library +FIND_PACKAGE(OpenSSL REQUIRED) +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() + +# if we found shared libraries - do the following: +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") + SET(BUILD_SHARED_LIBS ON) +ELSE() + MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL") +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(MUSL_STATIC AND NOT UMSKT_USE_SHARED_OPENSSL) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++") - 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() +# if we're compiling with MSVC, respect the DEBUG compile option +IF(MSVC) + SET(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + IF(NOT BUILD_SHARED_LIBS) + SET(CMAKE_CXX_FLAGS_RELEASE "/MT") + SET(CMAKE_CXX_FLAGS_DEBUG "/MTd") + ELSE() + SET(CMAKE_CXX_FLAGS_RELEASE "/MD") + SET(CMAKE_CXX_FLAGS_DEBUG "/MDd") + 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() -include(cmake/CPM.cmake) +IF(MUSL_STATIC) + MESSAGE(STATUS "[UMSKT] Performing a fully static build using muslc") + SET(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") + SET(CMAKE_SHARED_LINKER_FLAGS "-static -static-libgcc -static-libstdc++") + 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() +# initalize cpm.CMake +INCLUDE(cmake/CPM.cmake) + +# fetch cpm.CMake dependencies +# Include JSON development library CPMAddPackage( - NAME nlohmann_json - GITHUB_REPOSITORY nlohmann/json - VERSION 3.11.2 + NAME nlohmann_json + GITHUB_REPOSITORY nlohmann/json + VERSION 3.11.2 ) +# Include fmt development library CPMAddPackage( - NAME fmt - GITHUB_REPOSITORY fmtlib/fmt - GIT_TAG 10.0.0 - VERSION 10.0.0 + NAME fmt + GITHUB_REPOSITORY fmtlib/fmt + GIT_TAG 10.0.0 + VERSION 10.0.0 ) +# Include cmrc resource compiler CPMAddPackage( - NAME cmrc - GITHUB_REPOSITORY vector-of-bool/cmrc - GIT_TAG 2.0.1 - VERSION 2.0.1 + NAME cmrc + GITHUB_REPOSITORY vector-of-bool/cmrc + GIT_TAG 2.0.1 + VERSION 2.0.1 ) -# For Emscripten builds, set CMAKE_TOOLCHAIN_FILE to the appropriate file -set(EMSCRIPTEN_BUILD OFF CACHE BOOL "Build for Emscripten" FORCE) -if(EMSCRIPTEN_BUILD) - set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/cmake/Emscripten.cmake" CACHE STRING "Emscripten toolchain file") -endif() +# Include Crypto++ development library +#CPMAddPackage( +# NAME cryptopp-cmake +# GITHUB_REPOSITORY abdes/cryptopp-cmake +# GIT_TAG CRYPTOPP_8_8_0 +# VERSION 8.8.0 +# OPTIONS "CRYPTOPP_BUILD_TESTING OFF" +#) +#include googletest unit testing library +#CPMAddPackage( +# NAME googletest +# GITHUB_REPOSITORY google/googletest +# VERSION 1.13.0 +# OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt" +#) + +### 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/pidgen2/PIDGEN2.cpp - src/libumskt/debugoutput.cpp -) +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/pidgen2/PIDGEN2.cpp src/libumskt/debugoutput.cpp) -if(UMSKT_USE_SHARED_OPENSSL) - add_library(_umskt SHARED ${LIBUMSKT_SRC}) -else() - add_library(_umskt STATIC ${LIBUMSKT_SRC}) -endif() +#### Separate Build Path for emscripten +IF (EMSCRIPTEN) + ADD_EXECUTABLE(umskt ${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") -target_include_directories(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR}) -target_link_libraries(_umskt PRIVATE OpenSSL::Crypto fmt) + 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() + IF(NOT UMSKT_USE_SHARED_OPENSSL) + ### Static library compilation + ADD_LIBRARY(_umskt STATIC ${LIBUMSKT_SRC}) + TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES(_umskt -static OpenSSL::Crypto fmt ${UMSKT_LINK_LIBS}) + ELSE() + ### Shared library compilation + ADD_LIBRARY(_umskt SHARED ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL}) + TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES(_umskt OpenSSL::Crypto fmt ${UMSKT_LINK_LIBS}) + TARGET_LINK_DIRECTORIES(_umskt PUBLIC ${UMSKT_LINK_DIRS}) + ENDIF() -add_executable(umskt src/main.cpp src/cli.cpp ${UMSKT_EXE_WINDOWS_EXTRA}) + ### UMSKT executable compilation + ADD_EXECUTABLE(umskt src/main.cpp src/cli.cpp ${UMSKT_EXE_WINDOWS_EXTRA}) + TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${OPENSSL_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES(umskt _umskt OpenSSL::Crypto fmt nlohmann_json::nlohmann_json umskt::rc ${UMSKT_LINK_LIBS}) + TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS}) + IF(MSVC AND MSVC_MSDOS_STUB) + SET_PROPERTY(TARGET umskt APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB}) + ENDIF() -target_include_directories(umskt PUBLIC ${OPENSSL_INCLUDE_DIR}) -target_link_libraries(umskt PRIVATE _umskt OpenSSL::Crypto fmt nlohmann_json::nlohmann_json umskt::rc) + ### 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() diff --git a/README.md b/README.md index 61217f5..408fcc3 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,24 @@ [![libera.chat - #mspid](https://img.shields.io/badge/libera.chat-%23mspid-brightgreen)](https://web.libera.chat/gamja/?nick=Guest?#mspid) **Build status** -[![C/C++ CI (Linux)](https://github.com/UMSKT/UMSKT/actions/workflows/linux.yml/badge.svg)](../../actions/workflows/linux.yml) + [![C/C++ CI (Windows)](https://github.com/UMSKT/UMSKT/actions/workflows/windows.yml/badge.svg)](../../actions/workflows/windows.yml) + [![C/C++ CI (macOS)](https://github.com/UMSKT/UMSKT/actions/workflows/macos.yml/badge.svg)](../../actions/workflows/macos.yml) -[![C/C++ CI (DOS DJGPP)](https://github.com/UMSKT/UMSKT/actions/workflows/dos-djgpp.yml/badge.svg)](../../actions/workflows/freebsd.yml) + +[![C/C++ CI (Linux)](https://github.com/UMSKT/UMSKT/actions/workflows/linux.yml/badge.svg)](../../actions/workflows/linux.yml) + [![C/C++ CI (FreeBSD)](https://github.com/UMSKT/UMSKT/actions/workflows/freebsd.yml/badge.svg)](../../actions/workflows/dos-djgpp.yml) -Plan of Action / ToDo List +[![C/C++ CI (DOS DJGPP)](https://github.com/UMSKT/UMSKT/actions/workflows/dos-djgpp.yml/badge.svg)](../../actions/workflows/freebsd.yml) + +------ + +### Plan of Action / ToDo List In light of the recent exponential interest in this project I've decided to put updates of this project here: - Please see ticket #8 for more information +[Please see ticket #8 for more information](https://github.com/UMSKT/UMSKT/issues/8) ------ @@ -34,23 +41,28 @@ In light of the recent exponential interest in this project I've decided to put * It all comes down to four simple steps: +------ ### **Usage** #### 1. Download the latest version of UMSKT * *(GitHub account required)* - * Download the latest experimental version using the Actions tab ([Windows](../../actions/workflows/windows.yml?query=branch%3Amaster), [Linux](../../actions/workflows/linux.yml?query=branch%3Amaster), [macOS](../../actions/workflows/macos.yml?query=branch%3Amaster), [FreeBSD](../../actions/workflows/freebsd.yml?query=branch%3Amaster), [DOS DJGPP](../../actions/workflows/.yml?qudos-djgppery=branch%3Amaster)) + * Download the latest experimental version using the Actions tab ([Windows](../../actions/workflows/windows.yml?query=branch%3Amaster+is%3Asuccess), [Linux](../../actions/workflows/linux.yml?query=branch%3Amaster+is%3Asuccess), [macOS](../../actions/workflows/macos.yml?query=branch%3Amaster+is%3Asuccess), [FreeBSD](../../actions/workflows/freebsd.yml?query=branch%3Amaster+is%3Asuccess), [DOS DJGPP](../../actions/workflows/dos-djgpp.yml?query=branch%3Amaster+is%3Asuccess)) * ~~*(GitHub account \*not\* required)*~~ * ~~Download the latest release for your operating system and architecture from [the releases page](../../releases)~~ * No official releases right now, use the other method to get the latest version. -* **Note:** Before continuing, please ensure you have the `umskt` executable extracted. +* **Note:** Before continuing, please ensure you have the `umskt` executable extracted and on UNIX-like systems, have execution permissions (`chmod +x umskt`). -#### 2. Run `umskt` to generate a key, or add `--help` to see more options. +#### 2. Install OpenSSL 3.1.2. +For Windows, click [here](https://slproweb.com/products/Win32OpenSSL.html) and choose the right version. For other operating systems, consult your package manager. +*Note: This only applies if the build you download has OpenSSL embedded (static library) or not. You can usually tell if the download size is measured in KB or MB. If it's MB, you don't need this.* -#### 3. *(Activation step for `Retail` and `OEM` only)* +#### 3. Run `umskt` to generate a key, or add `--help` or `-h` to see more options. + +#### 4. *(Activation step for `Retail` and `OEM` only)* * After installation, you will be prompted to activate Windows. @@ -74,6 +86,7 @@ The list of people who have helped to bring the XP generation to where it is now * TheTank20 * InvoxiPlayGames * brakmic +* techguy16 (the list will be updated to add more collaborators) @@ -81,20 +94,26 @@ The list of people who have helped to bring the XP generation to where it is now ### **Development Requirements:** -* `CMake, make, gcc` (`build-essential`) +* `build-essential` + * `cmake` + * `make` + * `gcc` + * `g++` * `git` #### Build Steps: -1. `git clone` -2. `cd build/ && cmake ../ && make` +1. `git clone https://github.com/UMSKT/UMSKT` +2. `cd UMSKT/build` +3. `cmake ..` +4. `make` ----- ### **Known Ports** -| Language | Author | Repo URL | -|----------|-----------|-------------------------------------------------------| -| Rust | Alex Page | [anpage/umskt-rs](https://github.com/anpage/umskt-rs) | -| Python | techguy16 | [techguy16/umsktpy](https://github.com/techguy16/umsktpy) | +| Language | Author | Repo URL | +|----------|-----------|-----------------------------------------------------------| +| Rust | Alex Page | [anpage/umskt-rs](https://github.com/anpage/umskt-rs) | +| Python | techguy16 | [techguy16/umsktpy](https://github.com/techguy16/umsktpy) | diff --git a/keys.json b/keys.json index 6c174f7..3e6caef 100644 --- a/keys.json +++ b/keys.json @@ -45,6 +45,9 @@ "Office XP Applications": { "BINK": ["20", "21"] }, + "Works Suite 2003 and 2004": { + "BINK": ["20", "21"] + }, "Office XP": { "BINK": ["22", "23"] }, @@ -117,6 +120,9 @@ "Office 2003 Small Business": { "BINK": ["70", "71"] }, + "Office 2003 Student and Teacher": { + "BINK": ["70", "71"] + }, "Office 2003 Professional": { "BINK": ["72", "73"] }, @@ -1525,7 +1531,7 @@ } }, "Activation": { - "Windowws XP": { + "Windows XP": { "p": "102011604035381881", "x": { "0": "0", @@ -1568,4 +1574,4 @@ "iid_key": "1513142771" } } -} \ No newline at end of file +} diff --git a/src/cli.cpp b/src/cli.cpp index e150e61..80fe38f 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -53,6 +53,8 @@ void CLI::showHelp(char *argv[]) { 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"); @@ -69,16 +71,18 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) { "", "", "", + "", 640, 0, 1, - false, false, false, false, false, false, - MODE_BINK1998_GENERATE + false, + MODE_BINK1998_GENERATE, + WINDOWS }; for (int i = 1; i < argc; i++) { @@ -158,6 +162,28 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) { 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") { + options->productid = argv[i+1]; + i++; } else if (arg == "-V" || arg == "--validate") { if (i == argc - 1) { options->error = true; @@ -172,6 +198,11 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) { } } + // 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 == "") { + return options->error = true; + } + return !options->error; } @@ -220,6 +251,12 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) { int intBinkID; sscanf(options->binkid.c_str(), "%x", &intBinkID); + // FE and FF are BINK 1998, but do not generate valid keys, so we throw an error + if (intBinkID >= 0xFE) { + fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n"); + return 1; + } + 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; @@ -383,13 +420,8 @@ int CLI::BINK1998Generate() { // generate a key BN_sub(this->privateKey, this->genOrder, this->privateKey); - // Specify whether an upgrade version or not - bool bUpgrade = false; - if (options.upgrade == true) - bUpgrade = true; - for (int i = 0; i < this->total; i++) { - PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, bUpgrade, this->pKey); + PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, options.upgrade, this->pKey); bool isValid = PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey); if (isValid) { @@ -438,12 +470,7 @@ int CLI::BINK2002Generate() { fmt::print("> AuthInfo: {}\n", pAuthInfo); } - // Specify whether an upgrade version or not - bool bUpgrade = false; - if (options.upgrade == true) - bUpgrade = true; - - PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, bUpgrade, this->pKey); + PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, options.upgrade, this->pKey); bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey); if (isValid) { @@ -515,7 +542,7 @@ int CLI::BINK2002Validate() { int CLI::ConfirmationID() { char confirmation_id[49]; - int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id); + int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id, options.activationMode, options.productid); switch (err) { case ERR_TOO_SHORT: diff --git a/src/cli.h b/src/cli.h index f2bc7a6..43b329d 100644 --- a/src/cli.h +++ b/src/cli.h @@ -36,10 +36,18 @@ CMRC_DECLARE(umskt); +enum ACTIVATION_ALGORITHM { + WINDOWS = 0, + OFFICE_XP = 1, + OFFICE_2K3 = 2, + OFFICE_2K7 = 3, + PLUS_DME = 4, +}; + enum MODE { MODE_BINK1998_GENERATE = 0, MODE_BINK2002_GENERATE = 1, - MODE_CONFIRMATION_ID = 2, + MODE_CONFIRMATION_ID = 2, MODE_BINK1998_VALIDATE = 3, MODE_BINK2002_VALIDATE = 4, }; @@ -49,6 +57,7 @@ struct Options { std::string keysFilename; std::string instid; std::string keyToCheck; + std::string productid; int channelID; int serial; int numKeys; @@ -60,6 +69,7 @@ struct Options { bool list; MODE applicationMode; + ACTIVATION_ALGORITHM activationMode; }; class CLI { diff --git a/src/libumskt/confid/confid.cpp b/src/libumskt/confid/confid.cpp index b2a822c..e4040ec 100644 --- a/src/libumskt/confid/confid.cpp +++ b/src/libumskt/confid/confid.cpp @@ -29,9 +29,25 @@ #include "confid.h" -#define MOD 0x16A6B036D7F2A79ULL -#define NON_RESIDUE 43 -static const QWORD f[6] = {0, 0x21840136C85381ULL, 0x44197B83892AD0ULL, 0x1400606322B3B04ULL, 0x1400606322B3B04ULL, 1}; +QWORD MOD = 0; +QWORD NON_RESIDUE = 0; +QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; +int productID1; +int productID2; +int productID3; +int productID4; +int activationMode; + +int ConfirmationID::calculateCheckDigit(int pid) +{ + unsigned int i = 0, j = 0, k = 0; + for (j = pid; j; i += k) + { + k = j % 10; + j /= 10; + } + return ((10 * pid) - (i % 7)) + 7; +} QWORD ConfirmationID::residue_add(QWORD x, QWORD y) { @@ -95,18 +111,65 @@ QWORD ConfirmationID::ui128_quotient_mod(QWORD lo, QWORD hi) { // hi:lo * ceil(2**170/MOD) >> (64 + 64 + 42) QWORD prod1; - __umul128(lo, 0x604fa6a1c6346a87, &prod1); + switch (activationMode) { + case 0: + __umul128(lo, 0x604FA6A1C6346A87, &prod1); + break; + case 1: + case 2: + case 3: + __umul128(lo, 0x4FA8E4A40CDAE44A, &prod1); + break; + case 4: + __umul128(lo, 0x2C5C4D3654A594F0, &prod1); + } QWORD part1hi; - QWORD part1lo = __umul128(lo, 0x2d351c6d04f8b, &part1hi); + QWORD part1lo; + switch (activationMode) { + case 0: + part1lo = __umul128(lo, 0x2D351C6D04F8B, &part1hi); + break; + case 1: + case 2: + case 3: + part1lo = __umul128(lo, 0x2CBAF12A59BBE, &part1hi); + break; + case 4: + part1lo = __umul128(lo, 0x2D36C691A4EA5, &part1hi); + } QWORD part2hi; - QWORD part2lo = __umul128(hi, 0x604fa6a1c6346a87, &part2hi); + QWORD part2lo; + switch (activationMode) { + case 0: + part2lo = __umul128(hi, 0x604FA6A1C6346A87, &part2hi); + break; + case 1: + case 2: + case 3: + part2lo = __umul128(hi, 0x4FA8E4A40CDAE44A, &part2hi); + break; + case 4: + part2lo = __umul128(hi, 0x2C5C4D3654A594F0, &part2hi); + } QWORD sum1 = part1lo + part2lo; unsigned sum1carry = (sum1 < part1lo); sum1 += prod1; sum1carry += (sum1 < prod1); QWORD prod2 = part1hi + part2hi + sum1carry; QWORD prod3hi; - QWORD prod3lo = __umul128(hi, 0x2d351c6d04f8b, &prod3hi); + QWORD prod3lo; + switch (activationMode) { + case 0: + prod3lo = __umul128(hi, 0x2D351C6D04F8B, &prod3hi); + break; + case 1: + case 2: + case 3: + prod3lo = __umul128(hi, 0x2CBAF12A59BBE, &prod3hi); + break; + case 4: + prod3lo = __umul128(hi, 0x2D36C691A4EA5, &prod3hi); + } prod3lo += prod2; prod3hi += (prod3lo < prod2); return (prod3lo >> 42) | (prod3hi << 22); @@ -619,6 +682,20 @@ void ConfirmationID::sha1_single_block(unsigned char input[64], unsigned char ou output[16] = e >> 24; output[17] = e >> 16; output[18] = e >> 8; output[19] = e; } +void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version) +{ + QWORD buffer[5]; + int i; + for (i = 0; i < 5; i++) + memcpy(&buffer[i], (iid + (4 * i)), 4); + DWORD v1 = (buffer[3] & 0xFFFFFFF8) | 2; + DWORD v2 = ((buffer[3] & 7) << 29) | (buffer[2] >> 3); + QWORD hardwareIDVal = ((QWORD)v1 << 32) | v2; + for (i = 0; i < 8; ++i) + hwid[i] = (hardwareIDVal >> (8 * i)) & 0xFF; + *version = buffer[0] & 7; +} + void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize) { unsigned char sha1_input[64]; @@ -628,12 +705,26 @@ void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned c int external_counter; for (external_counter = 0; external_counter < 4; external_counter++) { memset(sha1_input, 0, sizeof(sha1_input)); - memcpy(sha1_input, buffer + half, half); - memcpy(sha1_input + half, key, keySize); - sha1_input[half + keySize] = 0x80; - sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8; - sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100; - sha1_single_block(sha1_input, sha1_result); + switch (activationMode) { + case 0: + case 1: + case 4: + memcpy(sha1_input, buffer + half, half); + memcpy(sha1_input + half, key, keySize); + sha1_input[half + keySize] = 0x80; + sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8; + sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100; + break; + case 2: + case 3: + sha1_input[0] = 0x79; + memcpy(sha1_input + 1, buffer + half, half); + memcpy(sha1_input + 1 + half, key, keySize); + sha1_input[1 + half + keySize] = 0x80; + sha1_input[sizeof(sha1_input) - 1] = (1 + half + keySize) * 8; + sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100; + } + sha1_single_block(sha1_input, sha1_result); size_t i; for (i = half & ~3; i < half; i++) sha1_result[i] = sha1_result[i + 4 - (half & 3)]; @@ -654,12 +745,26 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned int external_counter; for (external_counter = 0; external_counter < 4; external_counter++) { memset(sha1_input, 0, sizeof(sha1_input)); - memcpy(sha1_input, buffer, half); - memcpy(sha1_input + half, key, keySize); - sha1_input[half + keySize] = 0x80; - sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8; - sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100; - sha1_single_block(sha1_input, sha1_result); + switch (activationMode) { + case 0: + case 1: + case 4: + memcpy(sha1_input, buffer, half); + memcpy(sha1_input + half, key, keySize); + sha1_input[half + keySize] = 0x80; + sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8; + sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100; + break; + case 2: + case 3: + sha1_input[0] = 0x79; + memcpy(sha1_input + 1, buffer, half); + memcpy(sha1_input + 1 + half, key, keySize); + sha1_input[1 + half + keySize] = 0x80; + sha1_input[sizeof(sha1_input) - 1] = (1 + half + keySize) * 8; + sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100; + } + sha1_single_block(sha1_input, sha1_result); size_t i; for (i = half & ~3; i < half; i++) sha1_result[i] = sha1_result[i + 4 - (half & 3)]; @@ -671,8 +776,44 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned } } -int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49]) +int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid) { + int version; + unsigned char hardwareID[8]; + activationMode = mode; + switch (activationMode) { + case 0: + MOD = 0x16A6B036D7F2A79; + NON_RESIDUE = 43; + f[0] = 0x0; + f[1] = 0x21840136C85381; + f[2] = 0x44197B83892AD0; + f[3] = 0x1400606322B3B04; + f[4] = 0x1400606322B3B04; + f[5] = 0x1; + break; + case 1: + case 2: + case 3: + MOD = 0x16E48DD18451FE9; + NON_RESIDUE = 3; + f[0] = 0x0; + f[1] = 0xE5F5ECD95C8FD2; + f[2] = 0xFF28276F11F61; + f[3] = 0xFB2BD9132627E6; + f[4] = 0xE5F5ECD95C8FD2; + f[5] = 0x1; + break; + case 4: + MOD = 0x16A5DABA0605983; + NON_RESIDUE = 2; + f[0] = 0x334F24F75CAA0E; + f[1] = 0x1392FF62889BD7B; + f[2] = 0x135131863BA2DB8; + f[3] = 0x153208E78006010; + f[4] = 0x163694F26056DB; + f[5] = 0x1; + } unsigned char installation_id[19]; // 10**45 < 256**19 size_t installation_id_len = 0; const char* p = installation_id_str; @@ -714,7 +855,23 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_ return ERR_TOO_SHORT; for (; installation_id_len < sizeof(installation_id); installation_id_len++) installation_id[installation_id_len] = 0; - static const unsigned char iid_key[4] = {0x6A, 0xC8, 0x5E, 0xD4}; + unsigned char iid_key[4] = { 0x0, 0x0, 0x0, 0x0 }; + switch (activationMode) { + case 0: + case 4: + iid_key[0] = 0x6A; + iid_key[1] = 0xC8; + iid_key[2] = 0x5E; + iid_key[3] = 0xD4; + break; + case 1: + case 2: + case 3: + iid_key[0] = 0x5A; + iid_key[1] = 0x30; + iid_key[2] = 0xB9; + iid_key[3] = 0xF3; + } Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4); if (installation_id[18] >= 0x10) return ERR_UNKNOWN_VERSION; @@ -727,19 +884,65 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_ unsigned short KeySHA1; } parsed; #pragma pack(pop) - memcpy(&parsed, installation_id, sizeof(parsed)); - unsigned productId1 = parsed.ProductIDLow & ((1 << 17) - 1); - unsigned productId2 = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1); - unsigned productId3 = (parsed.ProductIDLow >> 27) & ((1 << 25) - 1); - unsigned version = (parsed.ProductIDLow >> 52) & 7; - unsigned productId4 = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9); - if (version != (totalCount == 41 ? 4 : 5)) - return ERR_UNKNOWN_VERSION; + switch (activationMode) { + case 0: + case 1: + case 4: + memcpy(&parsed, installation_id, sizeof(parsed)); + productID1 = parsed.ProductIDLow & ((1 << 17) - 1); + productID2 = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1); + productID3 = (parsed.ProductIDLow >> 27) & ((1 << 24) - 1); + version = (parsed.ProductIDLow >> 51) & 15; + productID4 = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9); + switch (activationMode) { + case 0: + if (version != (totalCount == 41 ? 9 : 10)) + return ERR_UNKNOWN_VERSION; + break; + case 1: + if (version != 1) + return ERR_UNKNOWN_VERSION; + break; + case 3: + if (version != 4) + return ERR_UNKNOWN_VERSION; + } + break; + case 2: + case 3: + decode_iid_new_version(installation_id, hardwareID, &version); + productID1 = stoi(productid.substr(0,5)); + std::string channelid = productid.substr(6,3); + char *p = &channelid[0]; + for (; *p; p++) { + *p = toupper((unsigned char)*p); + } + if (strcmp(&channelid[0], "OEM") == 0) { + productID2 = stoi(productid.substr(12,3)); + productID3 = calculateCheckDigit((stoi(productid.substr(15,1)) * 100000) + (stoi(productid.substr(18,5)))); + productID4 = (stoi((productid.substr(10,2))) / 100000) * 1000; + } else { + productID2 = stoi(productid.substr(6,3)); + productID3 = stoi(productid.substr(10,7)); + productID4 = stoi(productid.substr(18,5)); + } + switch (activationMode) { + case 2: + if (version != 3) + return ERR_UNKNOWN_VERSION; + break; + case 3: + if (version != 4) + return ERR_UNKNOWN_VERSION; + } + memcpy(&parsed, hardwareID, 8); + break; + } //printf("Product ID: %05u-%03u-%07u-%05u\n", productId1, productId2, productId3, productId4); unsigned char keybuf[16]; memcpy(keybuf, &parsed.HardwareID, 8); - QWORD productIdMixed = (QWORD)productId1 << 41 | (QWORD)productId2 << 58 | (QWORD)productId3 << 17 | productId4; + QWORD productIdMixed = (QWORD)productID1 << 41 | (QWORD)productID2 << 58 | (QWORD)productID3 << 17 | productID4; memcpy(keybuf + 8, &productIdMixed, 8); TDivisor d; @@ -754,7 +957,16 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_ } u; u.lo = 0; u.hi = 0; - u.buffer[7] = attempt; + switch (activationMode) { + case 0: + case 1: + case 4: + u.buffer[7] = attempt; + break; + case 2: + case 3: + u.buffer[6] = attempt; + } Mix(u.buffer, 14, keybuf, 16); QWORD x2 = ui128_quotient_mod(u.lo, u.hi); QWORD x1 = u.lo - x2 * MOD; @@ -766,7 +978,18 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_ } if (attempt > 0x80) return ERR_UNLUCKY; - divisor_mul128(&d, 0x04e21b9d10f127c1, 0x40da7c36d44c, &d); + switch (activationMode) { + case 0: + divisor_mul128(&d, 0x04E21B9D10F127C1, 0x40DA7C36D44C, &d); + break; + case 1: + case 2: + case 3: + divisor_mul128(&d, 0xEFE0302A1F7A5341, 0x01FB8CF48A70DF, &d); + break; + case 4: + divisor_mul128(&d, 0x7C4254C43A5D1181, 0x01C61212ECE610, &d); + } union { struct { QWORD encoded_lo, encoded_hi; diff --git a/src/libumskt/confid/confid.h b/src/libumskt/confid/confid.h index f96b9cb..ae2489f 100644 --- a/src/libumskt/confid/confid.h +++ b/src/libumskt/confid/confid.h @@ -41,6 +41,7 @@ typedef struct { } TDivisor; EXPORT class ConfirmationID { + static int calculateCheckDigit(int pid); static QWORD residue_add(QWORD x, QWORD y); static QWORD residue_sub(QWORD x, QWORD y); static QWORD __umul128(QWORD a, QWORD b, QWORD* hi); @@ -60,11 +61,12 @@ EXPORT class ConfirmationID { static void divisor_mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst); static unsigned rol(unsigned x, int shift); static void sha1_single_block(unsigned char input[64], unsigned char output[20]); + static void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version); static void Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize); static void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize); public: - static int Generate(const char* installation_id_str, char confirmation_id[49]); + static int Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid); //EXPORT static int CLIRun(); }; diff --git a/src/libumskt/libumskt.cpp b/src/libumskt/libumskt.cpp index 48d79b5..6293c14 100644 --- a/src/libumskt/libumskt.cpp +++ b/src/libumskt/libumskt.cpp @@ -27,8 +27,8 @@ #include "pidgen3/BINK2002.h" #include "pidgen2/PIDGEN2.h" -FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49]) { - return ConfirmationID::Generate(installation_id_str, confirmation_id); +FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid) { + return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid); } FNEXPORT EC_GROUP* PIDGEN3_initializeEllipticCurve(char* pSel, char* aSel, char* bSel, char* generatorXSel, char* generatorYSel, char* publicKeyXSel, char* publicKeyYSel, EC_POINT *&genPoint, EC_POINT *&pubPoint) { @@ -57,4 +57,4 @@ FNEXPORT int PIDGEN2_GenerateRetail(char* channelID, char* &keyout) { FNEXPORT int PIDGEN2_GenerateOEM(char* year, char* day, char* oem, char* keyout) { return PIDGEN2::GenerateOEM(year, day, oem, keyout); -} \ No newline at end of file +}