Compare commits

...

2 Commits

Author SHA1 Message Date
Neo-Desktop
7a0faa42e8 attempt to fix actions build 2024-02-21 18:33:32 -08:00
Neo-Desktop
c7eb049c0b update build scripts, add unit tests, pidgen2 needs polishing, confid is wip 2024-02-21 17:37:02 -08:00
44 changed files with 1433 additions and 758 deletions

View File

@ -23,21 +23,34 @@ name: C/C++ CI (DOS DJGPP)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
pull_request:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
workflow_dispatch:
env:
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
WATT_ROOT: ${{ github.workspace }}/djgpp/watt32
jobs:
build:
runs-on: ubuntu-latest
env:
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
GCC_EXEC_PREFIX: ${{ github.workspace }}/lib/gcc/
DJDIR: ${{ github.workspace }}/djgpp/i586-pc-msdosdjgpp
steps:
- name: Checkout Source Tree
uses: actions/checkout@v3
uses: actions/checkout@v4.1.1
- name: Set up CPM cache
id: cache-cpm
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cpm-cache
key: ${{ runner.os }}-cpm-${{ hashFiles('**/') }}
restore-keys: |
${{ runner.os }}-cpm-
- name: Setup build environment
run: |
@ -46,24 +59,19 @@ jobs:
- 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
git clone https://github.com/UMSKT/Watt-32.git watt32
cd watt32/util
make clean && make linux
cd ../src
source ${{ github.workspace }}/djgpp/setenv
./configur.sh djgpp
make -f djgpp.mak
ln -s ${WATT_ROOT}/lib/libwatt.a ${CMAKE_FIND_ROOT_PATH}/lib
echo "${{ github.workspace }}/djgpp/i586-pc-msdosdjgpp/bin/" >> "$GITHUB_ENV"
echo "${{ github.workspace }}/djgpp/bin/" >> "$GITHUB_ENV"
- name: Build
run: |
source ${{ github.workspace }}/djgpp/setenv
cmake -DDJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -DCMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} -DCMAKE_BUILD_TYPE=Release build/
cmake --build build/
- name: Build UMSKT for MSDOS via DJGPP
uses: threeal/cmake-action@v1.3.0
with:
options: UMSKT_DJGPP_COMPILE=On CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} CMAKE_BUILD_TYPE=Release
build-dir: build
c-compiler: ${CC}
cxx-compiler: ${CXX}
build-args: -j 2
- name: Move executable to upload directory
run: |
@ -71,7 +79,68 @@ jobs:
mv build/umskt.exe build/actions_upload/
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v4.3.1
with:
name: UMSKT-DOS
path: build/actions_upload
build-dos-win32-combined:
needs: build
runs-on: windows-latest
steps:
# 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: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Checkout Source Tree
uses: actions/checkout@v4.1.1
- name: Set up CPM cache
id: cache-cpm
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cpm-cache
key: ${{ runner.os }}-cpm-${{ hashFiles('**/') }}
restore-keys: |
${{ runner.os }}-cpm-
- name: Download Built DOS Artifact
uses: actions/download-artifact@v4.1.2
with:
name: UMSKT-DOS
- name: Configure and build UMSKT for DOS+Win32
uses: threeal/cmake-action@v1.3.0
with:
options: UMSKT_MSVC_WINXP=On CMAKE_BUILD_TYPE=Release CPM_SOURCE_CACHE=${{ github.workspace }}/.cpm-cache UMSKT_MSVC_MSDOS_STUB=${{ github.workspace }}/umskt.exe
generator: "Visual Studio 17 2022"
args: -A "Win32" -T "v141_xp"
run-build: true
build-args: "--config Release -j 2"
- name: Upload build artifact
uses: actions/upload-artifact@v4.3.1
with:
name: UMSKT-DOS+Win32
path: build/Release

View File

@ -17,46 +17,58 @@
#
# @FileCreated by techguy16 on 07/23/2023
# @Maintainer techguy16
name: C/C++ CI (FreeBSD)
on:
name: C/C++ CI (FreeBSD)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
pull_request:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
name: build-x86_64
steps:
- uses: actions/checkout@v3
- name: Build & Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
with:
usesh: true
prepare: |
pkg install -y cmake git bash
run: |
mkdir build
cmake -DCMAKE_BUILD_TYPE=Release build/
cmake --build build/
- 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: ubuntu-latest
name: build-x86_64
steps:
- name: Checkout Source Tree
uses: actions/checkout@v4.1.1
- name: Set up CPM cache
id: cache-cpm
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cpm-cache
key: ${{ runner.os }}-cpm-${{ hashFiles('**/') }}
restore-keys: |
${{ runner.os }}-cpm-
- name: Build & Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1.0.6
with:
usesh: true
prepare: |
pkg install -y cmake git bash
run: |
mkdir build
cmake -DCMAKE_BUILD_TYPE=Release -DCPM_SOURCE_CACHE= ${{ github.workspace }}/.cpm-cache -DBUILD_TESTING=On -B build/
cmake --build build/ -j 2
cd build
ctest
- 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@v4.3.1
with:
name: UMSKT-FreeBSD
path: build/actions_upload

View File

@ -23,7 +23,10 @@ name: C/C++ CI (Linux)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
pull_request:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
workflow_dispatch:
jobs:
@ -35,36 +38,52 @@ jobs:
- x86
- x86_64
- aarch64
- armhf
- armv7
- ppc64le
- s390x
steps:
- name: Checkout Source Tree
uses: actions/checkout@v3
- name: Checkout Source Tree
uses: actions/checkout@v4.1.1
- name: Setup latest Alpine Linux for ${{ matrix.arch }}
uses: jirutka/setup-alpine@v1
with:
packages: >
bash
build-base
cmake
git
musl-dev
arch: ${{ matrix.arch }}
shell-name: alpine-target.sh
- name: Set up CPM cache
id: cache-cpm
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cpm-cache
key: ${{ runner.os }}-cpm-${{ hashFiles('**/') }}
restore-keys: |
${{ runner.os }}-cpm-
- name: Configure and build UMSKT
uses: threeal/cmake-action@v1.3.0
with:
options: MUSL_STATIC=ON CMAKE_BUILD_TYPE=Release
run-build: true
shell: alpine-target.sh {0}
- name: Setup latest Alpine Linux for ${{ matrix.arch }}
uses: jirutka/setup-alpine@v1
with:
packages: >
bash
build-base
cmake
git
musl-dev
arch: ${{ matrix.arch }}
shell-name: alpine-target.sh
- name: Move files to correct directory
run: |
- name: Configure and build UMSKT
uses: threeal/cmake-action@v1.3.0
with:
options: UMSKT_MUSL_STATIC=ON CMAKE_BUILD_TYPE=Release CPM_SOURCE_CACHE=${{ github.workspace }}/.cpm-cache BUILD_TESTING=On
run-build: true
build-args: -j 2
run-test: true
shell: alpine-target.sh {0}
- 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-linux-${{ matrix.arch }}-static
path: build/actions_upload
- name: Upload build artifact
uses: actions/upload-artifact@v4.3.1
with:
name: UMSKT-linux-${{ matrix.arch }}-static
path: build/actions_upload

View File

@ -23,7 +23,10 @@ name: C/C++ CI (macOS)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
pull_request:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**' ] # If only these files are edited, skip
workflow_dispatch:
jobs:
@ -32,17 +35,29 @@ jobs:
strategy:
matrix:
arch:
- { name: arm64;x86_64, displayName: all-x86_64_arm64}
- { name: arm64;x86_64, displayName: all-x86_64_arm64 }
- { name: x86_64, displayName: x86_64 }
- { name: arm64, displayName: arm64 }
steps:
- name: Checkout Source Tree
uses: actions/checkout@v3
uses: actions/checkout@v4.1.1
- name: Configure and build UMSKT ${{ matrix.arch.displayName }}
run: |
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch.name }} build/
cmake --build build/
- name: Set up CPM cache
id: cache-cpm
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cpm-cache
key: ${{ runner.os }}-cpm-${{ hashFiles('**/') }}
restore-keys: |
${{ runner.os }}-cpm-
- name: Configure and build UMSKT for ${{ matrix.arch.displayName }}
uses: threeal/cmake-action@v1.3.0
with:
options: MUSL_STATIC=ON CMAKE_BUILD_TYPE=Release CPM_SOURCE_CACHE=${{ github.workspace }}/.cpm-cache CMAKE_OSX_ARCHITECTURES="${{ matrix.arch.name }}" BUILD_TESTING=On
run-build: true
build-args: -j 2
run-test: true
- name: Move files to correct directory
run: |
@ -50,7 +65,7 @@ jobs:
mv build/umskt build/actions_upload/umskt
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v4.3.1
with:
name: UMSKT-macOS-${{ matrix.arch.displayName }}
path: build/actions_upload

View File

@ -24,11 +24,17 @@ on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
pull_request:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
prepare:
build:
runs-on: windows-latest
strategy:
matrix:
arch: [ { name: Win32, displayName: x86 }, { name: x64, displayName: x64 } ]
steps:
# https://github.com/actions/runner-images/issues/6067#issuecomment-1213069040
- name: Install Windows XP Support for Visual Studio
@ -52,30 +58,33 @@ jobs:
exit 1
}
- name: Set up CPM cache
id: cache-cpm
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cpm-cache
key: ${{ runner.os }}-cpm-${{ hashFiles('**/') }}
restore-keys: |
${{ runner.os }}-cpm-
- name: Checkout Source Tree
uses: actions/checkout@v3
uses: actions/checkout@v4.1.1
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
build:
runs-on: windows-latest
needs: prepare
strategy:
matrix:
arch: [ { name: Win32, displayName: x86 }, { name: x64, displayName: x64} ]
steps:
- name: Configure and build UMSKT for ${{ matrix.values.displayName }}
uses: threeal/cmake-action@v1.3.0
with:
options: CMAKE_BUILD_TYPE=Release
options: CMAKE_BUILD_TYPE=Release CPM_SOURCE_CACHE=${{ github.workspace }}/.cpm-cache BUILD_TESTING=On
generator: "Visual Studio 17 2022"
args: -A "${{ matrix.arch.name }}" -T "v141_xp"
run-build: true
build-args: "--config Release"
build-args: --config Release -j 2
run-test: true
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v4.3.1
with:
name: UMSKT-${{ matrix.values.displayName }}
path: build/Release
path: build/Release

1
.gitignore vendored
View File

@ -3,6 +3,7 @@ build*/
*.exe
*.wasm
umskt
.cpm-cache
### NotepadPP template
# Notepad++ backups #

View File

@ -19,48 +19,55 @@
# @Maintainer Neo
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
PROJECT(UMSKT)
SET(PROJECT_NAME UMSKT)
PROJECT(${PROJECT_NAME})
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_OSX_SYSROOT "macosx" CACHE PATH "macOS SDK path")
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
OPTION(BUILD_SHARED_LIBS "Build all libraries as shared" 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" OFF)
OPTION(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF)
OPTION(BUILD_TESTING "Build testing binaries for CTest" OFF)
OPTION(BUILD_SHARED_LIBS "Build all dependant libraries as shared" OFF)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS})
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
OPTION(UMSKT_BUILD_SHARED_LIB "Build libumskt.so/.dll/.dylib" ON)
OPTION(UMSKT_BUILD_STATIC_LIB "Build libumskt_static.a/.lib" ON)
OPTION(UMSKT_MUSL_STATIC "Enable fully static builds in a muslc environment (i.e. Alpine Linux)" OFF)
OPTION(UMSKT_DJGPP_COMPILE "Enable compilation and linking with DJGPP" OFF)
OPTION(UMSKT_MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF)
OPTION(UMSKT_MSVC_WINXP "Specify compile-time flag overrides for Windows XP" OFF)
IF (NOT MSVC)
SET(CMAKE_CXX_FLAGS "-Os -fdata-sections -ffunction-sections -flto=auto -Wl,--gc-sections")
SET(CMAKE_CXX_FLAGS_DEBUG "-g")
SET(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall -Wextra")
SET(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall -Wextra -pedantic")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-Wall -Wextra")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-Wall -Wextra -pedantic")
SET(CMAKE_CXX_FLAGS_RELEASE_INIT "-s")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -Wl,--gc-sections")
ENDIF ()
IF (DJGPP_WATT32)
IF (UMSKT_DJGPP_COMPILE)
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)
SET(UMSKT_BUILD_SHARED_LIB OFF)
SET(UMSKT_BUILD_STATIC_LIB OFF)
SET(CMAKE_POSITION_INDEPENDENT_CODE OFF)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -march=i386 -mtune=i386")
MESSAGE(STATUS "[UMSKT] DJGPP Build requested - Shared libraries forced OFF")
ENDIF ()
IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(BUILD_SHARED_LIBS ON)
MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
MESSAGE(STATUS "[UMSKT] macOS Build requested - Shared libraries forced ON")
ENDIF ()
# if we're compiling with MSVC, respect the DEBUG compile option
IF (MSVC)
SET(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
SET(CMAKE_CXX_FLAGS "/O1 /GL /LTCG /Gy /OPT:REF /OPT:ICF /EHsc")
SET(CMAKE_CXX_FLAGS "/Os /LTCG /Gy /OPT:REF /OPT:ICF /EHsc")
SET(CMAKE_CXX_FLAGS_RELEASE "/MT")
SET(CMAKE_CXX_FLAGS_DEBUG "/MTd /Z7")
SET(CMAKE_EXE_LINKER_FLAGS "/INCREMENTAL:NO /NODEFAULTLIB:MSVCRT /LTCG")
@ -68,16 +75,18 @@ IF (MSVC)
SET(CMAKE_ENABLE_EXPORTS ON)
SET(UMSKT_EXE_WINDOWS_EXTRA src/windows/umskt.rc)
SET(UMSKT_EXE_WINDOWS_DLL src/windows/dllmain.cpp)
IF (UMSKT_MSVC_WINXP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /U_WIN32_WINNT /DWINVER=0x0501 /D_WIN32_WINNT=0x0501")
ENDIF ()
ENDIF ()
IF (MUSL_STATIC)
MESSAGE(STATUS "[UMSKT] Performing a fully static build using muslc")
MESSAGE(STATUS "[UMSKT] musl libc Build requested - Shared librares forced OFF")
SET(BUILD_SHARED_LIBS OFF)
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++")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
ENDIF ()
# initialize cpm.CMake
@ -88,6 +97,7 @@ FILE(
EXPECTED_HASH SHA256=cc155ce02e7945e7b8967ddfaff0b050e958a723ef7aad3766d368940cb15494
)
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake)
CPMUsePackageLock(${CMAKE_SOURCE_DIR}/package-lock.cmake)
# fetch cpm.CMake dependencies
# Include JSON development library
@ -113,23 +123,23 @@ CPMAddPackage(
VERSION 2.0.1
)
# Include stdint128
CPMAddPackage(
NAME stdint128
GITHUB_REPOSITORY UMSKT/stdint128-cmake
GIT_TAG v1.0.0
VERSION 1.0.0
)
# Include Crypto++ development library
CPMAddPackage(
NAME cryptopp-cmake
GITHUB_REPOSITORY abdes/cryptopp-cmake
GITHUB_REPOSITORY UMSKT/cryptopp-cmake
GIT_TAG CRYPTOPP_8_9_0
VERSION 8.9.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)
@ -137,8 +147,8 @@ 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/init.cpp src/libumskt/pidgen.cpp ${LIBUMSKT_PIDGEN2} ${LIBUMSKT_PIDGEN3} ${LIBUMSKT_CONFID})
SET(UMSKT_CLI_SRC src/main.cpp src/help.cpp src/cli.cpp src/generate.cpp)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} fmt cryptopp)
SET(UMSKT_CLI_SRC src/main.cpp src/cli/help.cpp src/cli/cli.cpp src/cli/confirmationid.cpp src/cli/options.cpp src/cli/pidgen.cpp)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} fmt cryptopp stdint128)
IF (NOT MSVC)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} umskt::rc)
@ -150,7 +160,7 @@ ENDIF()
#### Separate Build Path for emscripten
IF (EMSCRIPTEN)
ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${LIBUMSKT_SRC})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${CMAKE_BINARY_DIR})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${CMAKE_SOURCE_DIR}/src ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(umskt PUBLIC ${UMSKT_LINK_LIBS})
SET(CMAKE_EXECUTABLE_SUFFIX ".html")
@ -159,47 +169,96 @@ IF (EMSCRIPTEN)
SET_TARGET_PROPERTIES(umskt PROPERTIES LINK_FLAGS "-sWASM=1 -sEXPORT_ALL=1 -sEXPORTED_RUNTIME_METHODS=ccall,cwrap --no-entry")
ELSE ()
## umskt.so/.dll creation
ADD_LIBRARY(libumskt SHARED ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(libumskt PUBLIC ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(libumskt PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(libumskt PUBLIC ${UMSKT_LINK_LIBS})
IF (MSVC)
SET_TARGET_PROPERTIES(libumskt PROPERTIES OUTPUT_NAME libumskt)
ELSE ()
SET_TARGET_PROPERTIES(libumskt PROPERTIES OUTPUT_NAME umskt)
ENDIF ()
IF (UMSKT_BUILD_SHARED_LIB)
ADD_LIBRARY(libumskt SHARED ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(libumskt PUBLIC ${CMAKE_SOURCE_DIR}/src ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(libumskt PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(libumskt PUBLIC ${UMSKT_LINK_LIBS})
IF (MSVC)
SET_TARGET_PROPERTIES(libumskt PROPERTIES OUTPUT_NAME libumskt)
ELSE ()
SET_TARGET_PROPERTIES(libumskt PROPERTIES OUTPUT_NAME umskt)
ENDIF ()
ENDIF()
## umskt_static.a/.lib creation
ADD_LIBRARY(libumskt_static ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(libumskt_static PUBLIC ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(libumskt_static PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(libumskt_static PUBLIC ${UMSKT_LINK_LIBS})
IF (MSVC)
SET_TARGET_PROPERTIES(libumskt_static PROPERTIES OUTPUT_NAME libumskt_static)
ELSE ()
SET_TARGET_PROPERTIES(libumskt_static PROPERTIES OUTPUT_NAME umskt_static)
ENDIF ()
IF (UMSKT_BUILD_STATIC_LIB)
ADD_LIBRARY(libumskt_static ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(libumskt_static PUBLIC ${CMAKE_SOURCE_DIR}/src ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(libumskt_static PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(libumskt_static PUBLIC ${UMSKT_LINK_LIBS})
IF (MSVC)
SET_TARGET_PROPERTIES(libumskt_static PROPERTIES OUTPUT_NAME libumskt_static)
ELSE ()
SET_TARGET_PROPERTIES(libumskt_static PROPERTIES OUTPUT_NAME umskt_static)
ENDIF ()
ENDIF()
### UMSKT executable compilation
IF (NOT BUILD_SHARED_LIBS)
## Link against the static lib
ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_LINK_LIBRARIES(umskt PUBLIC libumskt_static ${UMSKT_LINK_LIBS} nlohmann_json::nlohmann_json)
ELSE ()
## Link against the dynamic lib
ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_LINK_LIBRARIES(umskt PUBLIC libumskt ${UMSKT_LINK_LIBS} nlohmann_json::nlohmann_json)
ENDIF()
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS})
IF (MSVC)
SET_PROPERTY(TARGET umskt APPEND PROPERTY COMPILE_FLAGS /DUMSKT_CLI_WINRC_EMBED_JSON)
IF (MSVC_MSDOS_STUB)
SET_PROPERTY(TARGET umskt APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB})
IF (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
### only build CLI if we're building UMSKT explicitly
IF (UMSKT_BUILD_STATIC_LIB)
## Link against the static lib
ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_LINK_LIBRARIES(umskt PUBLIC libumskt_static ${UMSKT_LINK_LIBS} nlohmann_json::nlohmann_json)
ELSEIF (UMSKT_BUILD_SHARED_LIB)
## Link against the dynamic lib
ADD_EXECUTABLE(umskt ${UMSKT_CLI_SRC} ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_LINK_LIBRARIES(umskt PUBLIC libumskt ${UMSKT_LINK_LIBS} nlohmann_json::nlohmann_json)
ELSE()
## Don't link against our output, do a full libumskt+cli compile
ADD_EXECUTABLE(umskt ${LIBUMSKT_SRC} ${UMSKT_CLI_SRC} ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_LINK_LIBRARIES(umskt PUBLIC ${UMSKT_LINK_LIBS} nlohmann_json::nlohmann_json)
ENDIF()
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${CMAKE_SOURCE_DIR}/src ${CMAKE_BINARY_DIR})
TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS})
IF (MSVC)
SET_PROPERTY(TARGET umskt APPEND PROPERTY COMPILE_FLAGS /DUMSKT_CLI_WINRC_EMBED_JSON)
IF (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 ()
ENDIF ()
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
INSTALL(TARGETS umskt DESTINATION bin)
ENDIF ()
### Strip the built binary
IF (${CMAKE_BUILD_TYPE} MATCHES "Release" AND NOT MSVC)
ADD_CUSTOM_COMMAND(TARGET umskt POST_BUILD
COMMAND strip $<TARGET_FILE:umskt>
COMMENT "Stripping symbols for release"
)
ENDIF()
ENDIF ()
#### Build Path for Unit Tests
IF ((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR UMSKT_BUILD_TESTING) AND BUILD_TESTING)
INCLUDE(CTest)
ENABLE_TESTING()
#include googletest unit testing library
CPMAddPackage(
NAME googletest
GITHUB_REPOSITORY google/googletest
VERSION 1.14.0
OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt"
)
MACRO(ADD_GTEST TEST)
ADD_EXECUTABLE(${TEST} ${ARGN})
TARGET_LINK_LIBRARIES(${TEST} gtest gmock gtest_main libumskt_static)
TARGET_COMPILE_FEATURES(${TEST} PRIVATE cxx_std_17)
SET_TARGET_PROPERTIES(${TEST} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests)
ADD_TEST(${TEST} tests/${TEST})
ENDMACRO()
ADD_GTEST(TEST_PIDGEN2 src/libumskt/pidgen2/PIDGEN2_unittest.cpp)
ADD_GTEST(TEST_PIDGEN3_BINK1998 src/libumskt/pidgen3/BINK1998_unittest.cpp)
ADD_GTEST(TEST_PIDGEN3_BINK2002 src/libumskt/pidgen3/BINK2002_unittest.cpp)
ADD_GTEST(TEST_CONFIRMATIONID src/libumskt/confid/confid_unittest.cpp)
ENDIF ()

View File

@ -27,9 +27,7 @@ RUN apk add --no-cache \
build-base \
cmake \
git \
musl-dev \
openssl-dev \
openssl-libs-static
musl-dev
# Stage 2: Build
@ -40,15 +38,15 @@ COPY . /src
# Build UMSKT from the local directory
RUN mkdir /src/build \
&& cmake -B /src/build -DMUSL_STATIC=ON \
&& cmake -B /src/build -DCPM_SOURCE_CACHE=/src/.cpm-cache -DCMAKE_BUILD_TYPE=Release -DUMSKT_MUSL_STATIC=ON \
&& cmake --build /src/build -j 10
# Stage 3: Output
FROM scratch as output
COPY --from=builder /src/build/umskt /umskt
COPY --from=builder /src/build/libumskt.a /umskt
COPY --from=builder /src/build/libumskt.so /umskt
COPY --from=builder /src/build/umskt /
COPY --from=builder /src/build/libumskt_static.a /
COPY --from=builder /src/build/libumskt.so /
# invoke via
# docker build -o type=tar,dest=umskt.tar .
# docker build -o type=tar,dest=build-musl/umskt.tar .

View File

@ -19,67 +19,55 @@
# @Maintainer Neo
# Stage 1: Install Prerequisites
#FROM ubuntu:latest as prerequisites
FROM ubuntu:latest as prerequisites
# Stage 1: Install build dependencies
#RUN apt-get update && apt-get -y install \
# build-essential \
# cmake \
# wget \
# 7zip \
# git \
# flex \
# libfl-dev \
# nasm \
# libslang2-dev \
# pkg-config \
# libslang2-modules \
# gcc-multilib \
# && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get -y install \
build-essential \
cmake \
wget \
7zip \
git \
flex \
libfl-dev \
nasm \
libslang2-dev \
pkg-config \
libslang2-modules \
gcc-multilib \
&& rm -rf /var/lib/apt/lists/*
FROM djgpp-prerequisites:latest as djgpp-watt32
FROM prerequisites as djgpp
SHELL ["/bin/bash", "-c"]
WORKDIR /
ENV CC=/djgpp/bin/i586-pc-msdosdjgpp-gcc CXX=/djgpp/bin/i586-pc-msdosdjgpp-g++ CMAKE_FIND_ROOT_PATH=/djgpp WATT_ROOT=/djgpp/watt32
ENV CC=/djgpp/bin/i586-pc-msdosdjgpp-gcc CXX=/djgpp/bin/i586-pc-msdosdjgpp-g++ CMAKE_FIND_ROOT_PATH=/djgpp
# Stage 2: compile WATT32 for D
# Stage 2: setup djgpp
RUN wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2 \
&& tar xjf djgpp-linux64-gcc1220.tar.bz2 \
&& rm -rf djgpp-linux64-gcc1220.tar.bz2 \
&& cd djgpp \
&& git clone https://github.com/UMSKT/Watt-32.git watt32 \
&& cd watt32/util \
&& make clean && make linux \
&& cd ../src \
&& source /djgpp/setenv \
&& ./configur.sh djgpp \
&& make -f djgpp.mak \
&& ln -s ${WATT_ROOT}/lib/libwatt.a ${CMAKE_FIND_ROOT_PATH}/lib
&& rm -rf djgpp-linux64-gcc1220.tar.bz2
# Stage 3: compile UMSKT
FROM djgpp-watt32 as build
FROM djgpp as build
SHELL ["/bin/bash", "-c"]
WORKDIR /src
COPY . /src
ENV PKG_CONFIG_PATH=/djgpp/lib/pkgconfig VERBOSE=1
# Build UMSKT from the local directory
RUN mkdir /src/build \
&& cd /src/build \
&& source /djgpp/setenv \
&& cmake -DDJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a .. \
&& make
&& cmake -DUMSKT_DJGPP_COMPILE=On -DCMAKE_BUILD_TYPE=Release -DCPM_SOURCE_CACHE=`pwd`/.cpm-cache -B build \
&& cmake --build build -j 10 --verbose
CMD ["bash"]
# Stage 6: Output
FROM scratch as output
COPY --from=build /src/build/umskt.exe /umskt.exe
COPY --from=build /src/build/umskt.exe /
# invoke via
# docker build -f Dockerfile.djgpp -o type=tar,dest=build-djgpp/umskt-dos.tar .

View File

@ -23,8 +23,8 @@
# Stage 1: Install Visual Studio
FROM mcr.microsoft.com/dotnet/framework/runtime:4.8.1 as visualstudio
# Download and install Build Tools for Visual Studio 2022 for native desktop workload.
#ADD https://aka.ms/vs/17/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe
ADD vs_buildtools.exe C:\TEMP\vs_buildtools.exe
ADD https://aka.ms/vs/17/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe
#ADD vs_buildtools.exe C:\TEMP\vs_buildtools.exe
RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache `
--add Microsoft.VisualStudio.Workload.VCTools `
--add Microsoft.VisualStudio.Workload.MSBuildTools `
@ -40,26 +40,15 @@ RUN ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass", "[System.Net.Ser
RUN ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass", "choco feature enable -n allowGlobalConfirmation"]
RUN ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass", "choco install git --params \"'/GitAndUnixToolsOnPath /WindowsTerminal /NoShellIntegration /NoGuiHereIntegration /NoShellHereIntegration /NoCredentialManager /SChannel'\""]
#Install OpenSSL 32bit 3.1.1
#ADD https://slproweb.com/download/Win32OpenSSL-3_1_1.msi C:\TEMP\Win32OpenSSL-3_1_1.msi
ADD Win32OpenSSL-3_1_1.msi C:\TEMP\Win32OpenSSL-3_1_1.msi
RUN msiexec /i C:\TEMP\Win32OpenSSL-3_1_1.msi /quiet /qn /norestart
#Install OpenSSL 64bit 3.1.1
#ADD https://slproweb.com/download/Win64OpenSSL-3_1_1.msi C:\TEMP\Win64OpenSSL-3_1_1.msi
ADD Win64OpenSSL-3_1_1.msi C:\TEMP\Win64OpenSSL-3_1_1.msi
RUN msiexec /i C:\TEMP\Win64OpenSSL-3_1_1.msi /quiet /qn /norestart
# Stage 3: Build the 32-bit version of UMSKT
FROM prereqisites as Build32
WORKDIR C:\umskt\
COPY . C:\umskt\
RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat && `
mkdir C:\umskt\build && `
cd C:\umskt\build && `
cmake -DMSVC_MSDOS_STUB:string=..\umskt.exe .. -G "Visual Studio 17 2022" -A "Win32" -T v141_xp && `
msbuild ALL_BUILD.vcxproj /P:Configuration=Release
mkdir C:\umskt\build && cd C:\umskt && `
cmake -B build -DCPM_SOURCE_CACHE=../.cpm-cache -DUMSKT_MSVC_WINXP=On -DCMAKE_BUILD_TYPE=Release -DMSVC_MSDOS_STUB=..\umskt.exe -G "Visual Studio 17 2022" -A "Win32" -T v141_xp && `
cmake --build build --config Release -j 10
# Stage 4: Build the 64-bit version of UMSKT
FROM prereqisites as Build64
@ -67,12 +56,10 @@ FROM prereqisites as Build64
WORKDIR C:\umskt\
COPY . C:\umskt\
ENV OPENSSL_ROOT_DIR="C:\Program Files\OpenSSL-Win64"
RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat && `
mkdir C:\umskt\build && `
cd C:\umskt\build && `
cmake .. && `
msbuild ALL_BUILD.vcxproj /P:Configuration=Release
cd C:\umskt && `
cmake -B build -DCPM_SOURCE_CACHE=../.cpm-cache -DCMAKE_BUILD_TYPE=Release && `
cmake --build build --config Release -j 10
# Stage 5: Copy binaries to an output/runtime image
FROM mcr.microsoft.com/dotnet/framework/runtime:4.8.1 as output

View File

@ -1235,21 +1235,6 @@
"y": "11647588982042777999933885074728841323429055317640349743317690400085264609368266409172384083304384956740124856614996"
}
},
"0B": {
"a": "1",
"b": "0",
"g": {
"x": "17272533675023793624680016937607161394427776688401278127884215858369066406365237833207419170117031265147050748737186",
"y": "10897684556651576571671151674586120690608236542740270859915076272932083320838022698730208293779451126638581586588925"
},
"n": "44682719955829289",
"p": "31123778862031392435299439090755153401162704597024288571183830527113563344679315725116915983118187065183839828632113",
"priv": "30177475288172038",
"pub": {
"x": "10584120526089473026246191383792758367144927589909587205278073830223938861208553884400816982485323081066790399437204",
"y": "19710761542152200618172612283139324015316083022563473705358032993141026289202915973780473937312193485361804450068338"
}
},
"0C": {
"a": "1",
"b": "0",

View File

@ -1,325 +0,0 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Andrew on 01/06/2023
* @Maintainer Neo
*/
#include "cli.h"
// define static storage
CLI::Options CLI::options;
json CLI::keys;
/**
*
* @param argcIn
* @param argvIn
* @return exit status (where success is 0)
*/
BYTE CLI::Init(int argcIn, char **argvIn)
{
// set default options
options.argc = argcIn;
options.argv = argvIn;
options.binkID = "2E";
options.productCode = "WINXP";
options.productFlavour = "VLK";
options.numKeys = 1;
options.pidgenversion = Options::PIDGEN_VERSION::PIDGEN_3;
options.state = Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE;
SetHelpText();
BOOL success = parseCommandLine();
if (!success)
{
return options.error;
}
// if we displayed help, without an error
// return success
if (options.help)
{
return -1;
}
success = processOptions();
if (!success)
{
return 2;
}
return 0;
}
/**
*
* @param filename
* @return success
*/
BOOL CLI::loadJSON(const fs::path &filename)
{
if (filename.empty())
{
if (options.verbose)
{
fmt::print("Loading internal keys file\n");
}
auto retval = loadEmbeddedJSON();
if (retval && options.verbose)
{
fmt::print("Loaded internal keys file successfully\n\n");
}
else if (!retval)
{
fmt::print("Error loading internal keys file...\n\n");
}
return retval;
}
if (!fs::exists(filename))
{
fmt::print("ERROR: File {} does not exist\n", filename.string());
return false;
}
if (options.verbose)
{
fmt::print("Loading keys file: {}\n", options.keysFilename);
}
std::ifstream f(filename);
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());
return false;
}
if (keys.is_discarded())
{
fmt::print("ERROR: Unable to parse keys from: {}\n", filename.string());
return false;
}
if (options.verbose)
{
fmt::print("Loaded keys from \"{}\" successfully\n", options.keysFilename);
}
return true;
}
/**
*
* @param pidgen3
* @return success
*/
BOOL CLI::InitPIDGEN3(PIDGEN3 *p3)
{
auto bink = keys["BINK"][options.binkID];
if (options.verbose)
{
fmt::print("{:->80}\n", "");
fmt::print("Loaded the following elliptic curve parameters: BINK[{}]\n", options.binkID);
fmt::print("{:->80}\n", "");
fmt::print("{:>6}: {}\n", "P", bink["p"]);
fmt::print("{:>6}: {}\n", "a", bink["a"]);
fmt::print("{:>6}: {}\n", "b", bink["b"]);
fmt::print("{:>6}: [{},\n{:>9}{}]\n", "G[x,y]", bink["g"]["x"], "", bink["g"]["y"]);
fmt::print("{:>6}: [{},\n{:>9}{}]\n", "K[x,y]", bink["pub"]["x"], "", bink["pub"]["y"]);
fmt::print("{:>6}: {}\n", "n", bink["n"]);
fmt::print("{:>6}: {}\n", "k", bink["priv"]);
fmt::print("\n");
}
p3->LoadEllipticCurve(options.binkID, bink["p"], bink["a"], bink["b"], bink["g"]["x"], bink["g"]["y"],
bink["pub"]["x"], bink["pub"]["y"], bink["n"], bink["priv"]);
if (options.state != Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE)
{
return true;
}
if (options.channelID.IsZero())
{
options.channelID.Randomize(UMSKT::rng, sizeof(DWORD32) * 8);
}
options.channelID %= 999;
p3->info.ChannelID = options.channelID;
if (options.verbose)
{
fmt::print("> Channel ID: {:d}\n", options.channelID);
}
if (options.serial.NotZero() && p3->checkFieldIsBink1998())
{
p3->info.Serial = options.serial;
if (options.verbose)
{
fmt::print("> Serial {:d}\n", options.serial);
}
}
else if (options.serial.NotZero() && !p3->checkFieldIsBink1998())
{
fmt::print("Warning: Discarding user-supplied serial for BINK2002\n");
}
return true;
}
/**
*
* @param confid
* @return success
*/
BOOL CLI::InitConfirmationID(ConfirmationID &confid)
{
if (!keys["products"][options.productCode].contains("meta") ||
!keys["products"][options.productCode]["meta"].contains("activation"))
{
fmt::print("ERROR: product flavour \"{}\" does not have known activation values", options.productCode);
return false;
}
auto meta = keys["products"][options.productCode]["meta"]["activation"];
if (!keys["activation"].contains(meta["flavour"]))
{
fmt::print("ERROR: \"{}\" is an unknown activation flavour", meta["flavour"]);
return false;
}
auto flavour = keys["activation"][meta["flavour"]];
if (options.verbose)
{
fmt::print("{:->80}\n", "");
fmt::print("Loaded the following hyperelliptic curve parameters: activation[{}]\n", meta["flavour"]);
fmt::print("{:->80}\n", "");
fmt::print("{:>7}: {}\n", "name", flavour["name"]);
fmt::print("{:>7}: {}\n", "version", meta["version"]);
fmt::print("{:>7}: {}\n", "Fp", flavour["p"]);
fmt::print("{:>7}: [{}, {}, {},\n{:>10}{}, {}, {}]\n", "F[]", flavour["x"]["0"], flavour["x"]["1"],
flavour["x"]["2"], "", flavour["x"]["3"], flavour["x"]["4"], flavour["x"]["5"]);
fmt::print("{:>7}: {}\n", "INV", flavour["quotient"]);
fmt::print("{:>7}: {}\n", "mqnr", flavour["non_residue"]);
fmt::print("{:>7}: {}\n", "k", flavour["priv"]);
fmt::print("{:>7}: {}\n", "IID", flavour["iid_key"]);
fmt::print("\n");
}
confid.LoadHyperellipticCurve(flavour["x"]["0"], flavour["x"]["1"], flavour["x"]["2"], flavour["x"]["3"],
flavour["x"]["4"], flavour["x"]["5"], flavour["priv"], flavour["quotient"],
flavour["non_residue"], flavour["iid_key"], meta["tags"].contains("xpbrand"),
meta["tags"].contains("office"), meta["activation"]["version"]);
return false;
}
/**
*
* @return success
*/
BOOL CLI::PIDGenerate()
{
BOOL retval = false;
if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_2)
{
auto p2 = PIDGEN2();
retval = PIDGEN2Generate(p2);
return retval;
}
else if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_3)
{
auto bink = keys["BINK"][options.binkID];
auto p3 = PIDGEN3::Factory(bink["p"]);
InitPIDGEN3(p3);
retval = PIDGEN3Generate(p3);
delete p3;
return retval;
}
return retval;
}
/**
*
* @return isValid
*/
BOOL CLI::PIDValidate()
{
BOOL retval = false;
if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_2)
{
auto p2 = PIDGEN2();
retval = PIDGEN2Validate(p2);
return retval;
}
else if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_3)
{
auto bink = keys["BINK"][options.binkID];
auto p3 = PIDGEN3::Factory(bink["p"]);
InitPIDGEN3(p3);
retval = PIDGEN3Validate(p3);
delete p3;
return retval;
}
return retval;
}
/**
* Process application state
*
* @return application status code
*/
int CLI::Run()
{
/**
* TODO: we should be checking if the system's pseudorandom facilities work
* before attempting generation, validation does not require entropy
*/
switch (options.state)
{
case Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE:
return PIDGenerate();
case Options::APPLICATION_STATE::STATE_PIDGEN_VALIDATE:
return PIDValidate();
case Options::APPLICATION_STATE::STATE_CONFIRMATION_ID:
return ConfirmationIDGenerate();
default:
return 1;
}
}

159
src/cli/cli.cpp Normal file
View File

@ -0,0 +1,159 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Andrew on 01/06/2023
* @Maintainer Neo
*/
#include "cli.h"
// define static storage
CLI::Options CLI::options;
json CLI::keys;
/**
*
* @param argcIn
* @param argvIn
* @return exit status (where success is 0)
*/
BYTE CLI::Init(int argcIn, char **argvIn)
{
// set default options
options.argc = argcIn;
options.argv = argvIn;
options.binkID = "2E";
options.productCode = "WINXP";
options.productFlavour = "VLK";
options.numKeys = 1;
options.pidgenversion = Options::PIDGEN_VERSION::PIDGEN_3;
options.state = Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE;
SetHelpText();
BOOL success = parseCommandLine();
if (!success)
{
return options.error;
}
// if we displayed help, without an error
// return success
if (options.help)
{
return -1;
}
success = processOptions();
if (!success)
{
return 2;
}
return 0;
}
/**
*
* @param filename
* @return success
*/
BOOL CLI::loadJSON(const fs::path &filename)
{
if (filename.empty())
{
if (options.verbose)
{
fmt::print("Loading internal keys file\n");
}
auto retval = loadEmbeddedJSON();
if (retval && options.verbose)
{
fmt::print("Loaded internal keys file successfully\n\n");
}
else if (!retval)
{
fmt::print("Error loading internal keys file...\n\n");
}
return retval;
}
if (!fs::exists(filename))
{
fmt::print("ERROR: File {} does not exist\n", filename.string());
return false;
}
if (options.verbose)
{
fmt::print("Loading keys file: {}\n", options.keysFilename);
}
std::ifstream f(filename);
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());
return false;
}
if (keys.is_discarded())
{
fmt::print("ERROR: Unable to parse keys from: {}\n", filename.string());
return false;
}
if (options.verbose)
{
fmt::print("Loaded keys from \"{}\" successfully\n", options.keysFilename);
}
return true;
}
/**
* Process application state
*
* @return application status code
*/
int CLI::Run()
{
/**
* TODO: we should be checking if the system's pseudorandom facilities work
* before attempting generation, validation does not require entropy
*/
switch (options.state)
{
case Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE:
return PIDGenerate();
case Options::APPLICATION_STATE::STATE_PIDGEN_VALIDATE:
return PIDValidate();
case Options::APPLICATION_STATE::STATE_CONFIRMATION_ID:
return ConfirmationIDGenerate();
default:
return 1;
}
}

View File

@ -23,8 +23,7 @@
#ifndef UMSKT_CLI_H
#define UMSKT_CLI_H
#include "libumskt/libumskt.h"
#include "typedefs.h"
#include <libumskt/libumskt.h>
#include <filesystem>
#include <fstream>
@ -32,7 +31,6 @@
#include <fmt/color.h>
#include <fmt/core.h>
#include <fmt/ostream.h>
#include <fmt/ranges.h>
#include <nlohmann/json.hpp>
@ -40,7 +38,7 @@ using json = nlohmann::json;
namespace fs = std::filesystem;
// fmt <-> json linkage
template <> struct fmt::formatter<json> : ostream_formatter
template <> struct fmt::formatter<json> : formatter<string_view>
{
auto format(const json &j, format_context &ctx) const
{
@ -50,18 +48,20 @@ template <> struct fmt::formatter<json> : ostream_formatter
}
else
{
return basic_ostream_formatter<char>::format(j, ctx);
std::stringstream s;
s << j;
return formatter<string_view>::format(s.str(), ctx);
}
}
};
#include "../libumskt/confid/confid.h"
#include "../libumskt/libumskt.h"
#include "../libumskt/pidgen2/PIDGEN2.h"
#include "../libumskt/pidgen3/BINK1998.h"
#include "../libumskt/pidgen3/BINK2002.h"
#include "../libumskt/pidgen3/PIDGEN3.h"
#include "help.h"
#include "libumskt/confid/confid.h"
#include "libumskt/libumskt.h"
#include "libumskt/pidgen2/PIDGEN2.h"
#include "libumskt/pidgen3/BINK1998.h"
#include "libumskt/pidgen3/BINK2002.h"
#include "libumskt/pidgen3/PIDGEN3.h"
#ifndef UMSKTCLI_VERSION_STRING
#define UMSKTCLI_VERSION_STRING "unknown version-dirty"

127
src/cli/confirmationid.cpp Normal file
View File

@ -0,0 +1,127 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 02/18/2024
* @Maintainer Neo
*/
#include "cli.h"
/**
*
* @param confid
* @return success
*/
BOOL CLI::InitConfirmationID(ConfirmationID &confid)
{
if (!keys["products"][options.productCode].contains("meta") ||
!keys["products"][options.productCode]["meta"].contains("activation"))
{
fmt::print("ERROR: product flavour \"{}\" does not have known activation values", options.productCode);
return false;
}
auto meta = keys["products"][options.productCode]["meta"]["activation"];
if (!keys["activation"].contains(meta["flavour"]))
{
fmt::print("ERROR: \"{}\" is an unknown activation flavour", meta["flavour"]);
return false;
}
auto flavour = keys["activation"][meta["flavour"]];
if (options.verbose)
{
fmt::print("{:->80}\n", "");
fmt::print("Loaded the following hyperelliptic curve parameters: activation[{}]\n", meta["flavour"]);
fmt::print("{:->80}\n", "");
fmt::print("{:>7}: {}\n", "name", flavour["name"]);
fmt::print("{:>7}: {}\n", "version", meta["version"]);
fmt::print("{:>7}: {}\n", "Fp", flavour["p"]);
fmt::print("{:>7}: [{}, {}, {},\n{:>10}{}, {}, {}]\n", "F[]", flavour["x"]["0"], flavour["x"]["1"],
flavour["x"]["2"], "", flavour["x"]["3"], flavour["x"]["4"], flavour["x"]["5"]);
fmt::print("{:>7}: {}\n", "INV", flavour["quotient"]);
fmt::print("{:>7}: {}\n", "mqnr", flavour["non_residue"]);
fmt::print("{:>7}: {}\n", "k", flavour["priv"]);
fmt::print("{:>7}: {}\n", "IID", flavour["iid_key"]);
fmt::print("\n");
}
confid.LoadHyperellipticCurve(flavour["x"]["0"], flavour["x"]["1"], flavour["x"]["2"], flavour["x"]["3"],
flavour["x"]["4"], flavour["x"]["5"], flavour["priv"], flavour["quotient"],
flavour["non_residue"], flavour["iid_key"], meta["tags"].contains("xpbrand"),
meta["tags"].contains("office"), meta["activation"]["version"]);
return false;
}
/**
*
* @return success
*/
BOOL CLI::ConfirmationIDGenerate()
{
auto confid = ConfirmationID();
std::string confirmation_id;
if (!InitConfirmationID(confid))
{
return false;
}
DWORD32 err = confid.Generate(options.installationID, confirmation_id, options.productID);
if (err == SUCCESS)
{
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 false;
}

View File

@ -37,7 +37,7 @@ void CLI::SetHelpText()
helpOptions[OPTION_DEBUG] = {"d", "debug", "enable debug output", false, "", &SetDebugOption};
helpOptions[OPTION_FILE] = {
"F", "file", "(advanced) specify which keys JSON file to load", true, "[embedded file]", &SetFileOption};
"", "file", "(advanced) specify which keys JSON file to load", true, "[embedded file]", &SetFileOption};
helpOptions[OPTION_LIST] = {"l", "list", "list supported products", false, "", &SetListOption};
@ -52,7 +52,7 @@ void CLI::SetHelpText()
true, "1", &SetNumberOption};
helpOptions[OPTION_ACTIVATIONID] = {
"i", "installationID", "(activation only) installation ID used to generate confirmation ID", true,
"I", "installationID", "(activation only) installation ID used to generate confirmation ID", true,
"", &SetActivationIDOption};
helpOptions[OPTION_ACTIVATIONPID] = {
@ -64,14 +64,14 @@ void CLI::SetHelpText()
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_BINK] = {"", "bink", "(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_CHANNELID] = {"", "channel", "(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",
"", "serial", "(advanced, PIDGEN 2/3 [BINK 1998] only) specify a serial to generate",
true, "", &SetSerialOption};
helpOptions[OPTION_AUTHDATA] = {
@ -331,9 +331,9 @@ BOOL CLI::processOptions()
}
// FE and FF are BINK 1998, but use a different, currently unhandled encoding scheme, we return an error here
if (options.binkID == "FE" || options.binkID == "FF")
if (options.binkID == "TS00" || options.binkID == "TS01")
{
fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n");
fmt::print("ERROR: Terminal Services BINKs (TS00 and TS01) are unsupported at this time\n");
return false;
}
@ -357,7 +357,7 @@ BOOL CLI::processListCommand()
// the following code is absolutely unhinged
// I'm so sorry
#if defined(__UNICODE__) || defined(__GNUC__)
#if defined(UNICODE) || defined(__GNUC__)
auto *leaf = "\u251C", *last = "\u2514", *line = "\u2500";
#else
auto *leaf = "\xC3", *last = "\xC0", *line = "\xC4";
@ -522,6 +522,7 @@ BOOL CLI::SetFileOption(const std::string &file)
fmt::print("Setting file option to: {}\n", file);
}
options.keysFilename = file;
return true;
}

3
src/cli/options.cpp Normal file
View File

@ -0,0 +1,3 @@
//
// Created by neo on 2/18/2024.
//

View File

@ -16,12 +16,72 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 01/05/2024
* @FileCreated by Neo on 02/18/2024
* @Maintainer Neo
*/
#include "cli.h"
/**
*
* @param pidgen3
* @return success
*/
BOOL CLI::InitPIDGEN3(PIDGEN3 *p3)
{
auto bink = keys["BINK"][options.binkID];
if (options.verbose)
{
fmt::print("{:->80}\n", "");
fmt::print("Loaded the following elliptic curve parameters: BINK[{}]\n", options.binkID);
fmt::print("{:->80}\n", "");
fmt::print("{:>6}: {}\n", "P", bink["p"]);
fmt::print("{:>6}: {}\n", "a", bink["a"]);
fmt::print("{:>6}: {}\n", "b", bink["b"]);
fmt::print("{:>6}: [{},\n{:>9}{}]\n", "G[x,y]", bink["g"]["x"], "", bink["g"]["y"]);
fmt::print("{:>6}: [{},\n{:>9}{}]\n", "K[x,y]", bink["pub"]["x"], "", bink["pub"]["y"]);
fmt::print("{:>6}: {}\n", "n", bink["n"]);
fmt::print("{:>6}: {}\n", "k", bink["priv"]);
fmt::print("\n");
}
p3->LoadEllipticCurve(options.binkID, bink["p"], bink["a"], bink["b"], bink["g"]["x"], bink["g"]["y"],
bink["pub"]["x"], bink["pub"]["y"], bink["n"], bink["priv"]);
if (options.state != Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE)
{
return true;
}
if (options.channelID.IsZero())
{
options.channelID.Randomize(UMSKT::rng, sizeof(DWORD32) * 8);
}
options.channelID %= 999;
p3->info.ChannelID = options.channelID;
if (options.verbose)
{
fmt::print("> Channel ID: {:d}\n", options.channelID);
}
if (options.serial.NotZero() && p3->checkFieldIsBink1998())
{
p3->info.Serial = options.serial;
if (options.verbose)
{
fmt::print("> Serial {:d}\n", options.serial);
}
}
else if (options.serial.NotZero() && !p3->checkFieldIsBink1998())
{
fmt::print("Warning: Discarding user-supplied serial for BINK2002\n");
}
return true;
}
/**
*
* @param pidgen2
@ -59,6 +119,23 @@ BOOL CLI::PIDGEN2Generate(PIDGEN2 &p2)
*/
BOOL CLI::PIDGEN2Validate(PIDGEN2 &p2)
{
std::string product_key;
if (!p2.ValidateKeyString(options.keyToCheck, product_key))
{
fmt::print("ERROR: Product key is in an incorrect format!\n");
return false;
}
fmt::print("{}\n", p2.StringifyKey(product_key));
if (!p2.Validate(product_key))
{
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
return false;
}
fmt::print("Key validated successfully!\n");
return true;
}
@ -165,7 +242,7 @@ BOOL CLI::PIDGEN3Validate(PIDGEN3 *p3)
{
std::string product_key;
if (!PIDGEN3::ValidateKeyString(options.keyToCheck, product_key))
if (!p3->ValidateKeyString(options.keyToCheck, product_key))
{
fmt::print("ERROR: Product key is in an incorrect format!\n");
return false;
@ -187,54 +264,56 @@ BOOL CLI::PIDGEN3Validate(PIDGEN3 *p3)
*
* @return success
*/
BOOL CLI::ConfirmationIDGenerate()
BOOL CLI::PIDGenerate()
{
auto confid = ConfirmationID();
std::string confirmation_id;
BOOL retval = false;
if (!InitConfirmationID(confid))
if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_2)
{
return false;
auto p2 = PIDGEN2();
retval = PIDGEN2Generate(p2);
return retval;
}
else if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_3)
{
auto bink = keys["BINK"][options.binkID];
auto p3 = PIDGEN3::Factory(bink["p"]);
InitPIDGEN3(p3);
retval = PIDGEN3Generate(p3);
delete p3;
return retval;
}
DWORD32 err = confid.Generate(options.installationID, confirmation_id, options.productID);
if (err == SUCCESS)
{
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 false;
return retval;
}
/**
*
* @return isValid
*/
BOOL CLI::PIDValidate()
{
BOOL retval = false;
if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_2)
{
auto p2 = PIDGEN2();
retval = PIDGEN2Validate(p2);
return retval;
}
else if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_3)
{
auto bink = keys["BINK"][options.binkID];
auto p3 = PIDGEN3::Factory(bink["p"]);
InitPIDGEN3(p3);
retval = PIDGEN3Validate(p3);
delete p3;
return retval;
}
return retval;
}

View File

@ -24,6 +24,8 @@
* the history provided by diamondggg is that they are the originator of the code
* and was created in tandem with an acquaintance who knows number theory.
* The file dates suggest this code was written sometime in 2017/2018
*
* The algorithm was refactored by Neo in 2023
* }
*/
@ -102,14 +104,14 @@ BOOL ConfirmationID::LoadHyperellipticCurve(const std::string *f, const std::str
{
for (int i = 0; i < 6; i++)
{
Integer(&f[i][0]).Encode((BYTE *)curve[i], sizeof(QWORD));
EncodeN(IntegerS(f[i]), curve[i]);
}
Integer(&priv[0]).Encode(privateKey.byte, sizeof(Q_OWORD));
EncodeN(IntegerS(priv), privateKey);
Integer(&modulus[0]).Encode((BYTE *)&MOD, sizeof(QWORD));
EncodeN(IntegerS(modulus), MOD);
Integer(&nonresidue[0]).Encode((BYTE *)NON_RESIDUE, sizeof(QWORD));
EncodeN(IntegerS(nonresidue), NON_RESIDUE);
this->isOffice = isOffice;
this->isXPBrand = isXPBrand;

View File

@ -23,7 +23,7 @@
#ifndef UMSKT_CONFID_H
#define UMSKT_CONFID_H
#include "../libumskt.h"
#include <libumskt/libumskt.h>
// Confirmation ID generator constants
enum CONFIRMATION_ID_STATUS
@ -44,7 +44,7 @@ typedef struct
Q_OWORD u, v;
} TDivisor;
class EXPORT ConfirmationID
class EXPORT ConfirmationID : public UMSKT
{
QWORD MOD = 0, NON_RESIDUE = 0;
QWORD curve[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

View File

@ -0,0 +1,55 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 02/20/2024
* @Maintainer Neo
*/
#include "confid.h"
#include <libumskt/libumskt_unittest.h>
/**
* ConfirmationID must not be an abstract class.
*/
TEST(TestConfirmationID, InstantiateConfirmationID)
{
auto p3 = new ConfirmationID();
ASSERT_NE(p3, nullptr);
delete p3;
}
class TestConfirmationID : public libumsktUnitTests
{
protected:
ConfirmationID *cid;
void SetUp() override
{
cid = new ConfirmationID();
cid->LoadHyperellipticCurve()
}
void TearDown() override
{
if (cid != nullptr)
{
delete cid;
cid = nullptr;
}
}
};

View File

@ -20,7 +20,7 @@
* @Maintainer Neo
*/
#include "libumskt.h"
#include <libumskt/libumskt.h>
std::FILE *UMSKT::debug;
std::FILE *UMSKT::verbose;
@ -38,7 +38,7 @@ BOOL UMSKT::CONSTRUCT()
{
#ifdef __DJGPP__
// this should be set up as early as possible
auto now = uclock();
uclock();
#endif
return true;
}

View File

@ -20,12 +20,12 @@
* @Maintainer Neo
*/
#include "libumskt.h"
#include "confid/confid.h"
#include "pidgen2/PIDGEN2.h"
#include "pidgen3/BINK1998.h"
#include "pidgen3/BINK2002.h"
#include "pidgen3/PIDGEN3.h"
#include <libumskt/confid/confid.h>
#include <libumskt/libumskt.h>
#include <libumskt/pidgen2/PIDGEN2.h>
#include <libumskt/pidgen3/BINK1998.h>
#include <libumskt/pidgen3/BINK2002.h>
#include <libumskt/pidgen3/PIDGEN3.h>
std::map<UMSKT_TAG, UMSKT_Value> UMSKT::tags;
CryptoPP::DefaultAutoSeededRNG UMSKT::rng;

View File

@ -23,7 +23,7 @@
#ifndef UMSKT_LIBUMSKT_H
#define UMSKT_LIBUMSKT_H
#include "../typedefs.h"
#include <typedefs.h>
#ifdef __DJGPP__
#include <time.h>
@ -43,7 +43,6 @@ using Integer = CryptoPP::Integer;
#include <fmt/core.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
// fmt <-> CryptoPP linkage
template <> class fmt::formatter<Integer>
@ -229,6 +228,21 @@ class EXPORT UMSKT
return EncodeN(in, (BYTE *)&buf, sizeof(T));
}
/**
* Encode Integer to Native type T where T is a concrete type
*
* @tparam T
* @param in
* @param buf
* @return
*/
template <typename T = DWORD32> INLINE static T EncodeN(const Integer &in)
{
T buf;
EncodeN(in, (BYTE *)&buf, sizeof(T));
return buf;
}
/**
* Encode a random number into a Native concrete type
*

View File

@ -0,0 +1,39 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 02/19/2024
* @Maintainer Neo
*/
#ifndef UMSKT_LIBUMSKT_UNITTEST_H
#define UMSKT_LIBUMSKT_UNITTEST_H
#include <gtest/gtest.h>
#include <libumskt/libumskt.h>
class libumsktUnitTests : public testing::Test
{
public:
libumsktUnitTests()
{
// UMSKT::setVerboseOutput(stderr);
// UMSKT::setDebugOutput(stderr);
}
~libumsktUnitTests() override = default;
};
#endif // UMSKT_LIBUMSKT_UNITTEST_H

View File

@ -34,15 +34,36 @@
class PIDGEN : public UMSKT
{
public:
virtual ~PIDGEN() = default;
static const Integer SEVEN;
static const Integer TEN;
static const Integer MaxChannelID;
static const Integer MaxSerial;
virtual BOOL Generate(std::string &pKey) = 0;
virtual BOOL Validate(const std::string &pKey) = 0;
virtual std::string StringifyKey(const std::string &pKey) = 0;
virtual std::string StringifyProductID() = 0;
virtual BOOL Generate(std::string &pKey)
{
throw std::runtime_error("PIDGEN::Generate() pure virtual function call");
}
virtual BOOL Validate(const std::string &pKey)
{
throw std::runtime_error("PIDGEN::Validate() pure virtual function call");
}
virtual std::string StringifyKey(const std::string &pKey)
{
throw std::runtime_error("PIDGEN::StringifyKey() pure virtual function call");
}
virtual std::string StringifyProductID()
{
throw std::runtime_error("PIDGEN::StringifyProductID() pure virtual function call");
}
virtual BOOL ValidateKeyString(const std::string &in_key, std::string &out_key)
{
throw std::runtime_error("PIDGEN::ValidateKeyString() pure virtual function call");
}
Integer GenerateMod7(const Integer &in);
BOOL isValidMod7(const Integer &in);

View File

@ -36,38 +36,21 @@ BOOL PIDGEN2::Generate(std::string &pKey)
Integer random;
random.Randomize(rng, sizeof(DWORD32) * 8);
info.ChannelID = random % MaxChannelID;
if (!isValidChannelID())
{
info.ChannelID++;
if (info.ChannelID <= Integer::Zero())
{
info.ChannelID = Integer::One();
}
else if (info.ChannelID >= 999)
{
info.ChannelID = 998;
}
}
random.Randomize(rng, sizeof(DWORD32) * 8);
info.Serial = random % MaxSerial;
info.ChannelID = info.ChannelID % MaxChannelID;
info.Serial = info.Serial % MaxSerial;
if (info.isOEM)
{
info.Day = (random % Integer(365)) + Integer::One();
info.Year = IntegerS(validYears[random % validYears.size()]);
info.Day = info.Day % Integer(366);
// info.Year = info.Year;
info.OEMID = (info.ChannelID * TEN) + (info.Serial / (MaxSerial / TEN));
info.Serial %= (MaxSerial / TEN);
info.OEMID = (info.OEMID * TEN) + GenerateMod7(info.OEMID);
DWORD32 day, year, serial, oemid;
EncodeN(info.Day, day);
EncodeN(info.Year, year);
EncodeN(info.Serial, serial);
EncodeN(info.OEMID, oemid);
DWORD32 day = EncodeN(info.Day), year = EncodeN(info.Year), serial = EncodeN(info.Serial),
oemid = EncodeN(info.OEMID);
if (debug)
{
@ -81,9 +64,7 @@ BOOL PIDGEN2::Generate(std::string &pKey)
info.ChannelID = (info.ChannelID * TEN) + ((info.ChannelID % TEN) + 1);
info.Serial = (info.Serial * TEN) + GenerateMod7(info.Serial);
DWORD32 channelid, serial;
EncodeN(info.ChannelID, channelid);
EncodeN(info.Serial, serial);
DWORD32 channelid = EncodeN(info.ChannelID), serial = EncodeN(info.Serial);
if (debug)
{
@ -96,11 +77,7 @@ BOOL PIDGEN2::Generate(std::string &pKey)
{
info.Serial = (info.Serial * TEN) + GenerateMod7(info.Serial);
fmt::print("{}\n", info.Serial);
DWORD32 channelid, serial;
EncodeN(info.ChannelID, channelid);
EncodeN(info.Serial, serial);
DWORD32 channelid = EncodeN(info.ChannelID), serial = EncodeN(info.Serial);
if (debug)
{
@ -142,7 +119,7 @@ BOOL PIDGEN2::Generate(std::string &pKey)
BOOL PIDGEN2::Validate(const std::string &pKey)
{
std::string filtered;
std::copy_if(pKey.begin(), pKey.end(), std::back_inserter(filtered), [](char c) { return std::isdigit(c); });
ValidateKeyString(pKey, filtered);
bool bIsValidChannelID, bIsValidSerial, bIsValidOEMDay, bIsValidOEMYear, bIsValidOEMID;
@ -241,6 +218,19 @@ std::string PIDGEN2::StringifyProductID()
return fmt::format("{}-{}", info.ChannelID, info.Serial);
}
/**
*
* @param in_key
* @param out_key
* @return
*/
BOOL INLINE PIDGEN2::ValidateKeyString(const std::string &in_key, std::string &out_key)
{
std::copy_if(in_key.begin(), in_key.end(), std::back_inserter(out_key), [](char c) { return std::isdigit(c); });
return out_key.length() == KeySize::FPP || out_key.length() == KeySize::Office || out_key.length() == KeySize::OEM;
}
/**
* Is the Serial with check digit a valid serial?
*

View File

@ -23,7 +23,7 @@
#ifndef UMSKT_PIDGEN2_H
#define UMSKT_PIDGEN2_H
#include "../pidgen.h"
#include <libumskt/pidgen.h>
class EXPORT PIDGEN2 : public PIDGEN
{
@ -38,6 +38,8 @@ class EXPORT PIDGEN2 : public PIDGEN
};
public:
~PIDGEN2() override = default;
struct KeyInfo
{
BOOL isOEM, isOffice;
@ -48,6 +50,7 @@ class EXPORT PIDGEN2 : public PIDGEN
BOOL Validate(const std::string &pKey) override;
std::string StringifyKey(const std::string &pKey) override;
std::string StringifyProductID() override;
BOOL ValidateKeyString(const std::string &in_key, std::string &out_key) override;
BOOL isValidSerial();
BOOL isValidOEMID();

View File

@ -0,0 +1,115 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 02/19/2024
* @Maintainer Neo
*/
#include "PIDGEN2.h"
#include <libumskt/libumskt_unittest.h>
/**
* PIDGEN2 must not be an abstract class.
*/
TEST(PIDGEN2, InstantiatePIDGEN2)
{
auto p2 = new PIDGEN2();
ASSERT_NE(p2, nullptr);
delete p2;
}
class TestPIDGEN2 : public libumsktUnitTests
{
protected:
PIDGEN *p;
PIDGEN2 *p2;
PIDGEN2::KeyInfo valid_ki = {false, false, 60, 99, 0, 95, 111111};
void SetUp() override
{
p2 = new PIDGEN2();
}
void TearDown() override
{
if (p != nullptr)
{
delete p;
p = nullptr;
}
if (p2 != nullptr)
{
delete p2;
p2 = nullptr;
}
}
};
TEST_F(TestPIDGEN2, TestStringifyKeyFPP)
{
std::string pKey = "0951111111";
pKey = p2->StringifyKey(pKey);
ASSERT_STRCASEEQ(&pKey[0], "095-1111111");
}
TEST_F(TestPIDGEN2, TestStringifyKeyOffice)
{
std::string pKey = "09561111111";
pKey = p2->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "0956-1111111");
}
TEST_F(TestPIDGEN2, TestStringifyKeyOEM)
{
std::string pKey = "06099000951611111";
pKey = p2->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "06099-OEM-0009516-11111");
}
TEST_F(TestPIDGEN2, GenerateValidFPPKey)
{
p2->info = valid_ki;
std::string pKey;
p2->Generate(pKey);
pKey = p2->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "095-1111111");
}
TEST_F(TestPIDGEN2, GenerateValidOfficeKey)
{
p2->info = valid_ki;
p2->info.isOffice = true;
std::string pKey;
p2->Generate(pKey);
pKey = p2->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "0956-1111111");
}
TEST_F(TestPIDGEN2, GenerateValidOEMKey)
{
p2->info = valid_ki;
p2->info.isOEM = true;
std::string pKey;
p2->Generate(pKey);
pKey = p2->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "06099-OEM-0009516-11111");
}

View File

@ -99,6 +99,11 @@ BOOL BINK1998::Generate(std::string &pKey)
// copy initial state from object
auto ki = info;
if (!ki.Rand.IsZero())
{
c = ki.Rand;
}
// Data segment of the RPK.
Integer serialPack = (ki.ChannelID * MaxSerial) + ki.Serial;
Integer pData = (serialPack << 1) | ki.isUpgrade;
@ -110,8 +115,11 @@ BOOL BINK1998::Generate(std::string &pKey)
{
ECP::Point R;
// Generate a random number c consisting of 384 bits without any constraints.
c.Randomize(UMSKT::rng, FieldBits);
if (ki.Rand.IsZero())
{
// Generate a random number c consisting of 384 bits without any constraints.
c.Randomize(UMSKT::rng, FieldBits);
}
// Pick a random derivative of the base point on the elliptic curve.
// R = cG;
@ -201,7 +209,7 @@ BOOL BINK1998::Generate(std::string &pKey)
fmt::print(verbose, "\n");
}
} while (ki.Signature.BitCount() > 55);
} while (ki.Signature.BitCount() > 55 && ki.Rand.IsZero());
// ↑ ↑ ↑
// The signature can't be longer than 55 bits, else it will
// make the CD-key longer than 25 characters.
@ -237,13 +245,13 @@ BOOL BINK1998::Validate(const std::string &pKey)
if (verbose)
{
fmt::print(UMSKT::verbose, "Validation results:\n");
fmt::print(UMSKT::verbose, "{:>10}: {}\n", "Upgrade", (bool)ki.isUpgrade);
fmt::print(UMSKT::verbose, "{:>10}: {}\n", "Channel ID", ki.ChannelID);
fmt::print(UMSKT::verbose, "{:>10}: {}\n", "Sequence", ki.Serial);
fmt::print(UMSKT::verbose, "{:>10}: {:x}\n", "Hash", ki.Hash);
fmt::print(UMSKT::verbose, "{:>10}: {:x}\n", "Signature", ki.Signature);
fmt::print(UMSKT::verbose, "\n");
fmt::print(verbose, "Validation results:\n");
fmt::print(verbose, "{:>10}: {}\n", "Upgrade", (bool)ki.isUpgrade);
fmt::print(verbose, "{:>10}: {}\n", "Channel ID", ki.ChannelID);
fmt::print(verbose, "{:>10}: {}\n", "Sequence", ki.Serial);
fmt::print(verbose, "{:>10}: {:x}\n", "Hash", ki.Hash);
fmt::print(verbose, "{:>10}: {:x}\n", "Signature", ki.Signature);
fmt::print(verbose, "\n");
}
Integer serialPack = (ki.ChannelID * MaxSerial) + ki.Serial;
@ -280,7 +288,7 @@ BOOL BINK1998::Validate(const std::string &pKey)
if (debug)
{
fmt::print("\nP[x,y]: [{:x},\n{:x}]\n\n", P.x, P.y);
fmt::print(debug, "P[x,y]: [{:x},\n{:x}]\n\n", P.x, P.y);
}
BYTE msgDigest[SHA1::DIGESTSIZE], msgBuffer[SHAMessageLength], *pMsgBuffer = msgBuffer;

View File

@ -39,6 +39,8 @@ class EXPORT BINK1998 : public PIDGEN3
eCurve = p3->eCurve;
}
~BINK1998() override = default;
static constexpr DWORD32 FieldBits = (48 * 8);
static constexpr DWORD32 FieldBytes = (FieldBits / 8);
static constexpr DWORD32 SHAMessageLength = (4 + 2 * FieldBytes);

View File

@ -0,0 +1,110 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 02/19/2024
* @Maintainer Neo
*/
#include "../libumskt_unittest.h"
#include "BINK1998.h"
/**
* BINK1998 must not be an abstract class.
*/
TEST(PIDGEN3_BINK1998, InstantiateBINK1998)
{
auto p3 = new BINK1998();
ASSERT_NE(p3, nullptr);
delete p3;
}
class TestBINK1998 : public libumsktUnitTests
{
protected:
PIDGEN *p;
PIDGEN3 *p3;
BINK1998 *bink1998;
BINK1998::KeyInfo valid_ki = {false, false, 640, 111111, 0};
void SetUp() override
{
bink1998 = new BINK1998();
bink1998->LoadEllipticCurve("0x2E",
"2260481414313563299067995668434431120981995280321627195247220485552475627515144045"
"6421260165232069708317717961315241",
"1", "0",
"1091074492220651278115691316907175015302838688467620894706280834607253141127048943"
"2930252839559606812441712224597826",
"1917099366991720451749161800061981867915210969017264186834961288993048036527467509"
"6509477191800826190959228181870174",
"1439923035396364333971294001595406158106423983592682351741971676961393703934682226"
"9422480779920783799484349086780408",
"5484731395987446993229594927733430043632089703338918322171291299699820472711849119"
"800714736923107362018017833200634",
"61760995553426173", "37454031876727861");
bink1998->info = valid_ki;
}
void TearDown() override
{
if (bink1998 != nullptr)
{
delete bink1998;
bink1998 = nullptr;
}
if (p3 != nullptr)
{
delete p3;
p3 = nullptr;
}
if (p != nullptr)
{
p = nullptr;
}
}
};
TEST_F(TestBINK1998, ValidateValidKeyString)
{
std::string pKey;
auto ValidateKeyString = bink1998->ValidateKeyString("7KWK7-9W7H4-T64D6-DB8V7-BW7MW", pKey);
ASSERT_TRUE(ValidateKeyString);
ASSERT_STREQ(&pKey[0], "7KWK79W7H4T64D6DB8V7BW7MW");
}
TEST_F(TestBINK1998, ValidateValidKey)
{
std::string pKey = "7KWK79W7H4T64D6DB8V7BW7MW";
auto Validate = bink1998->Validate(pKey);
ASSERT_TRUE(Validate);
}
TEST_F(TestBINK1998, GenerateValidKey)
{
bink1998->info.Rand = UMSKT::IntegerS("3427338792529164195109698841758932126727183763685994848291878088992924483488"
"5768429236548372772607190036626858221847");
std::string pKey;
bink1998->Generate(pKey);
pKey = bink1998->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "7KWK7-9W7H4-T64D6-DB8V7-BW7MW");
}

View File

@ -44,7 +44,7 @@ Integer BINK2002::Pack(const KeyInfo &ki)
if (debug)
{
fmt::print("pack: {:x}\n\n", raw);
fmt::print(debug, "pack: {:x}\n\n", raw);
}
return raw;
@ -97,6 +97,11 @@ BOOL BINK2002::Generate(std::string &pKey)
Integer c, e, s, pRaw;
if (!ki.Rand.IsZero())
{
c = ki.Rand;
}
// Data segment of the RPK.
Integer pData = ki.ChannelID << 1 | ki.isUpgrade;
@ -106,8 +111,11 @@ BOOL BINK2002::Generate(std::string &pKey)
{
ECP::Point R;
// Generate a random number c consisting of 512 bits without any constraints.
c.Randomize(UMSKT::rng, FieldBits);
if (ki.Rand.IsZero())
{
// Generate a random number c consisting of 512 bits without any constraints.
c.Randomize(UMSKT::rng, FieldBits);
}
// R = cG
R = eCurve.Multiply(c, genPoint);
@ -135,19 +143,19 @@ BOOL BINK2002::Generate(std::string &pKey)
if (debug)
{
fmt::print("msgBuffer[1]: ");
fmt::print(debug, "msgBuffer[1]: ");
for (BYTE b : msgBuffer)
{
fmt::print("{:x}", b);
fmt::print(debug, "{:x}", b);
}
fmt::print("\n\n");
fmt::print(debug, "\n\n");
fmt::print("msgDigest[1]: ");
fmt::print(debug, "msgDigest[1]: ");
for (BYTE b : msgDigest)
{
fmt::print("{:x}", b);
fmt::print(debug, "{:x}", b);
}
fmt::print("\n\n");
fmt::print(debug, "\n\n");
}
// Translate the byte sha1 into a 32-bit integer - this is our computed hash.
@ -159,12 +167,12 @@ BOOL BINK2002::Generate(std::string &pKey)
BYTE buf[8];
sha1.CalculateTruncatedDigest(buf, sizeof(buf), msgBuffer, SHAMessageLength);
fmt::print("truncated buffer: ");
fmt::print(verbose, "truncated buffer: ");
for (BYTE b : buf)
{
fmt::print("{:x}", b);
fmt::print(verbose, "{:x}", b);
}
fmt::print("\n\n");
fmt::print(verbose, "\n\n");
DWORD h0 = ((DWORD)buf[0] | ((DWORD)buf[1] << 8) | ((DWORD)buf[2] << 16) | ((DWORD)buf[3] << 24));
DWORD h1 =
@ -173,11 +181,11 @@ BOOL BINK2002::Generate(std::string &pKey)
h1 |= (h0 >> 31) & 1;
fmt::print("h0,1: {:x} {:x}\n\n", h0, h1);
fmt::print(verbose, "h0,1: {:x} {:x}\n\n", h0, h1);
ki.Serial = IntegerN(h1);
fmt::print("serial: {:d}\n\n", ki.Serial);
fmt::print(verbose, "serial: {:d}\n\n", ki.Serial);
}
// Assemble the second SHA message.
@ -200,19 +208,19 @@ BOOL BINK2002::Generate(std::string &pKey)
if (debug)
{
fmt::print("msgBuffer[2]: ");
fmt::print(debug, "msgBuffer[2]: ");
for (BYTE b : msgBuffer)
{
fmt::print("{:x}", b);
fmt::print(debug, "{:x}", b);
}
fmt::print("\n\n");
fmt::print(debug, "\n\n");
fmt::print("msgDigest[2]: ");
fmt::print(debug, "msgDigest[2]: ");
for (BYTE b : msgDigest)
{
fmt::print("{:x}", b);
fmt::print(debug, "{:x}", b);
}
fmt::print("\n\n");
fmt::print(debug, "\n\n");
}
// Translate the byte sha1 into a 64-bit integer - this is our computed intermediate signature.
@ -298,7 +306,7 @@ BOOL BINK2002::Generate(std::string &pKey)
fmt::print(verbose, "{:>10}: {:x}\n", "AuthInfo", ki.AuthInfo);
fmt::print(verbose, "\n");
}
} while (ki.Signature.BitCount() > 62 || noSquare);
} while ((ki.Signature.BitCount() > 62 || noSquare) && ki.Rand.IsZero());
// ↑ ↑ ↑
// The signature can't be longer than 62 bits, else it will
// overlap with the AuthInfo segment next to it.
@ -402,7 +410,7 @@ BOOL BINK2002::Validate(const std::string &pKey)
if (debug)
{
fmt::print("P[x,y]: [{:x},\n{:x}]\n\n", P.x, P.y);
fmt::print(debug, "P[x,y]: [{:x},\n{:x}]\n\n", P.x, P.y);
}
// Assemble the second SHA message.

View File

@ -39,6 +39,8 @@ class EXPORT BINK2002 : public PIDGEN3
eCurve = p3->eCurve;
}
~BINK2002() override = default;
static constexpr DWORD32 FieldBits = (64 * 8);
static constexpr DWORD32 FieldBytes = (FieldBits / 8);
static constexpr DWORD32 SHAMessageLength = (3 + 2 * FieldBytes);

View File

@ -0,0 +1,121 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 02/19/2024
* @Maintainer Neo
*/
#include "BINK2002.h"
#include <libumskt/libumskt_unittest.h>
/**
* BINK2002 must not be an abstract class.
*/
TEST(PIDGEN3_BINK2002, InstantiateBINK2002)
{
auto p3 = new BINK2002();
ASSERT_NE(p3, nullptr);
delete p3;
}
class TestBINK2002 : public libumsktUnitTests
{
protected:
PIDGEN *p;
PIDGEN3 *p3;
BINK2002 *bink2002;
BINK2002::KeyInfo valid_ki = {false, false, 640, 0, 701};
void SetUp() override
{
bink2002 = new BINK2002();
bink2002->LoadEllipticCurve("0x54",
"1250964251969733259611431105354461862074700938981465222536952118871017192617497641"
"9995384745134703589248167610052719613586668754176591418831031596093374569",
"1", "0",
"8059057663701168311917532277618827622978515614146963913097592614451721430413021070"
"395782723330339842826599481063797559797462512297834269467666807971588275",
"1223930383017475319177970597922037862339473226753699711562597963240231208768364492"
"7405756146495100825573682155171145924668759419114616275413724686284123408",
"4895832170509729140211911021638266775170167022247175324972987673313207244495397975"
"379010973250279668424167408883454560376269866102669741515127286188717976",
"5846013328426281815512452704859777850382010968846722453046994319336479079120767834"
"777937190955827245502389471872759584209649693396095099112777776298051208",
"5622613991231344109", "1285511085175426271");
bink2002->info = valid_ki;
}
void TearDown() override
{
if (bink2002 != nullptr)
{
delete bink2002;
bink2002 = nullptr;
}
if (p3 != nullptr)
{
delete p3;
p3 = nullptr;
}
if (p != nullptr)
{
p = nullptr;
}
}
};
TEST_F(TestBINK2002, ValidateValidKeyString)
{
std::string pKey;
auto ValidateKeyString = bink2002->ValidateKeyString("QX7C7-6668G-RHTTC-9XXD6-4QKVM", pKey);
ASSERT_TRUE(ValidateKeyString);
ASSERT_STREQ(&pKey[0], "QX7C76668GRHTTC9XXD64QKVM");
}
TEST_F(TestBINK2002, ValidateInvalidKeyString)
{
std::string pKey;
auto ValidateKeyString = bink2002->ValidateKeyString("QX7C7-6668G-RHTTC-9XXD6-4QKVM-7", pKey);
ASSERT_FALSE(ValidateKeyString);
}
TEST_F(TestBINK2002, ValidateValidKey)
{
std::string pKey = "QX7C76668GRHTTC9XXD64QKVM";
auto Validate = bink2002->Validate(pKey);
ASSERT_TRUE(Validate);
}
TEST_F(TestBINK2002, ValidateInvalidKey)
{
std::string pKey = "QX7C76668GRHTTC9XXD64QKV7";
auto Validate = bink2002->Validate(pKey);
ASSERT_FALSE(Validate);
}
TEST_F(TestBINK2002, GenerateValidKey)
{
bink2002->info.Rand = UMSKT::IntegerS("2715417548459431244234182116258933974639514924173191881913315754156057922856"
"789413383072541627152533502894944768632184791880876163762899980230935");
std::string pKey;
bink2002->Generate(pKey);
pKey = bink2002->StringifyKey(pKey);
ASSERT_STREQ(&pKey[0], "QX7C7-6668G-RHTTC-9XXD6-4QKVM");
}

View File

@ -290,10 +290,10 @@ std::string PIDGEN3::StringifyKey(const std::string &pKey)
* @param currentChar
* @return
*/
std::string PIDGEN3::ValidateStringKeyInputCharset(std::string &accumulator, char currentChar)
std::string INLINE PIDGEN3::ValidateStringKeyInputCharset(std::string &accumulator, char currentChar)
{
char cchar = (char)::toupper(currentChar);
if (std::find(pKeyCharset.begin(), pKeyCharset.begin(), cchar) != pKeyCharset.end())
if (std::find(pKeyCharset.begin(), pKeyCharset.end(), cchar) != pKeyCharset.end())
{
accumulator.push_back(cchar);
}

View File

@ -23,7 +23,7 @@
#ifndef UMSKT_PIDGEN3_H
#define UMSKT_PIDGEN3_H
#include "../pidgen.h"
#include <libumskt/pidgen.h>
class BINK1998;
class BINK2002;
@ -51,14 +51,12 @@ class EXPORT PIDGEN3 : public PIDGEN
eCurve = p3.eCurve;
}
virtual ~PIDGEN3()
{
}
~PIDGEN3() override = default;
struct KeyInfo
{
Integer Serial = 0, AuthInfo = 0, ChannelID = 0, Hash = 0, Signature = 0, Rand = 0;
BOOL isUpgrade = false, isOEM = false;
Integer ChannelID = 0, Serial = 0, AuthInfo = 0, Rand = 0, Hash = 0, Signature = 0;
void setSerial(DWORD32 SerialIn)
{
@ -88,15 +86,22 @@ class EXPORT PIDGEN3 : public PIDGEN
BOOL Validate(const std::string &pKey) override;
std::string StringifyKey(const std::string &pKey) override;
std::string StringifyProductID() override;
BOOL ValidateKeyString(const std::string &in_key, std::string &out_key) override;
virtual Integer Pack(const KeyInfo &ki) = 0;
virtual KeyInfo Unpack(const Integer &raw) = 0;
virtual Integer Pack(const KeyInfo &ki)
{
throw std::runtime_error("PIDGEN3::Pack() pure virtual function call");
}
virtual KeyInfo Unpack(const Integer &raw)
{
throw std::runtime_error("PIDGEN3::Unpack() pure virtual function call");
}
// PIDGEN3.cpp
static PIDGEN3 *Factory(const std::string &field);
static BOOL checkFieldStrIsBink1998(std::string keyin);
static std::string ValidateStringKeyInputCharset(std::string &accumulator, char currentChar);
static BOOL ValidateKeyString(const std::string &in_key, std::string &out_key);
static std::string base24(Integer &seq);
static Integer unbase24(const std::string &cdKey);

View File

@ -20,7 +20,7 @@
* @Maintainer Neo
*/
#include "cli.h"
#include <cli/cli.h>
int main(int argc, char *argv[])
{

View File

@ -20,7 +20,7 @@
* @Maintainer Neo
*/
#include "cli.h"
#include <cli/cli.h>
#include <cmrc/cmrc.hpp>
CMRC_DECLARE(umskt);

View File

@ -25,20 +25,23 @@
#if defined(_MSC_VER)
// squelch the insane amount of warnings from cstdbool
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <intrin.h>
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#endif // defined(_MSC_VER)
#include <algorithm>
#include <cctype>
#include <cstdbool>
#include <cstdint>
#include <iostream>
#include <map>
#include <numeric>
#include <sstream>
#include <stdint128>
#include <string>
#include <vector>
@ -88,15 +91,6 @@ using WORD = uint16_t;
using DWORD = unsigned long;
using DWORD32 = uint32_t;
using QWORD = uint64_t;
#if defined(__SIZEOF_INT128__) || defined(__int128)
using uint128_t = unsigned __int128;
#elif defined(_MSC_VER) && defined(_M_ARM) // for Windows on ARM ??
using uint128_t = __n128;
#else // use the intel-supplied __m128 intrisic from <intrin.h>
using uint128_t = __m128;
#endif
using OWORD = uint128_t;
typedef union {

View File

@ -20,8 +20,8 @@
* @Maintainer Neo
*/
#include "../typedefs.h"
#include "resource.h"
#include "typedefs.h"
BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle, IN DWORD nReason, IN LPVOID Reserved)
{

View File

@ -20,7 +20,7 @@
* @Maintainer Neo
*/
#include "../cli.h"
#include "cli/cli.h"
#include "resource.h"
/**

Binary file not shown.