To slop SSL away (#191)

* windows 98/nt4, slopped openssl away

* one (1) roadblock that it can't figure out

* fixed maybe

* fix dos?

* fix dos? (2)

* ts is gonna be slow

* No need to compress anymore

* No need to compress anymore (2)

* deslop

The main problem with AI models, even today, is that they're very shortsighted. They're too focused on the thing working now than thinking about how maintainable it will be later. As such, you get duplicated code, as well as comments that are geared towards what it's doing right then and there (as if it's an advertisement of it's services) rather than improving the readability of the code. Always check your diffs.

* Update workflows

* Update freebsd.yml

* Update README.md
This commit is contained in:
TheTank20 authored and GitHub committed 2026-10-30 16:53:17 -04:00
1 parent 4a6cb3cd31
commit f9100e0871
41 files changed
+4758 -1743

No files matched your search

+6 -171
View File
@@ -33,19 +33,18 @@ 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
steps:
- name: Checkout Source Tree
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Setup build environment
run: |
sudo apt -y update
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib dosbox tree
sudo apt -y install build-essential cmake wget 7zip git gcc-multilib dosbox tree
- name: Download and Setup DJGPP Toolchain
run: |
@@ -54,41 +53,7 @@ jobs:
tar xjf djgpp-linux64-gcc1220.tar.bz2
cd ${{ github.workspace }}/djgpp
tree . -S
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 ${{ github.workspace }}/djgpp/lib
- name: Cache OpenSSL 3.1.2
uses: actions/cache/restore@v4
id: cache-openssl
with:
path: |
${{ github.workspace }}/djgpp
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
- name: Checkout and Cross Compile OpenSSL 3.1.2
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: |
git clone https://github.com/UMSKT/openssl.git openssl
pushd openssl
source ${{ github.workspace }}/djgpp/setenv
./Configure 386 no-threads no-tests no-sse2 no-asm -DOPENSSL_DEV_NO_ATOMICS -mno-mmx -mno-sse -mno-sse2 -march=i386 --prefix=${{ github.workspace }}/djgpp DJGPP
make && make install_sw
popd
- name: Save OpenSSL 3.1.2
if: steps.cache-openssl.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/djgpp
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
- name: Download stub
run: |
wget https://web.archive.org/web/20250308092209/https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/util/system/cwsdpmi/csdpmi7b.zip -O CSDPMI7B.ZIP
@@ -99,7 +64,7 @@ jobs:
run: |
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} -D CWSDSTUB_LOCATION=/home/runner/dpmibin/CWSDSTUB.EXE -D DJGPP_BIN_LOCATION=/home/runner/work/UMSKT/UMSKT/djgpp/i586-pc-msdosdjgpp/bin
cmake ../ -D DJGPP=ON -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} -D CWSDSTUB_LOCATION=/home/runner/dpmibin/CWSDSTUB.EXE -D DJGPP_BIN_LOCATION=/home/runner/work/UMSKT/UMSKT/djgpp/i586-pc-msdosdjgpp/bin
make
- name: Setup DOSBox test environment
@@ -145,7 +110,7 @@ jobs:
- name: Run tests in DOSBox
run: |
cd dosbox_test
timeout 30s dosbox -conf dosbox.conf -nogui -exit
timeout 2m dosbox -conf dosbox.conf -nogui -exit
# Check if the test completed successfully
if [ ! -f DONE.TXT ]; then
echo "Tests did not complete successfully"
@@ -199,137 +164,7 @@ jobs:
mv build/umskt.exe build/actions_upload/
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@v7
with:
name: UMSKT-DOS-x86
path: build/actions_upload
compress:
needs: build
if: success()
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- name: Setup test environment
run: |
sudo apt -y update
sudo apt -y install dosbox
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: UMSKT-DOS-x86
path: .
- name: Install UPX
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
- name: Compress binary
shell: pwsh
run: |
upx umskt.exe --best --ultra-brute -v
- name: Setup DOSBox test environment
run: |
mkdir -p dosbox_test
cp umskt.exe dosbox_test/
# Download DPMI server directly
# wget https://github.com/UMSKT/winactiontest/raw/refs/heads/main/CWSDPMI.EXE -O dosbox_test/CWSDPMI.EXE
# Create test batch file
cat > dosbox_test/test.bat << EOL
@echo off
echo Running test 1...
umskt.exe -b 2C -c 365 -s 069420,999999 > TEST1.TXT
if errorlevel 1 goto error
echo Running test 2...
umskt.exe -b 5A -c 640 -s 069420,999999 > TEST2.TXT
if errorlevel 1 goto error
echo Running test 3...
umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST3.TXT
if errorlevel 1 goto error
echo Tests completed > DONE.TXT
goto end
:error
echo Test failed > ERROR.TXT
:end
exit
EOL
# Create DOSBox configuration
cat > dosbox_test/dosbox.conf << EOL
[sdl]
nosound=true
[cpu]
cputype=386
core=dynamic
cycles=max
[autoexec]
mount c .
c:
test.bat
exit
EOL
- name: Run tests in DOSBox
run: |
cd dosbox_test
timeout 30s dosbox -conf dosbox.conf -nogui -exit
# Check if the test completed successfully
if [ ! -f DONE.TXT ]; then
echo "Tests did not complete successfully"
if [ -f ERROR.TXT ]; then
echo "Test execution failed"
fi
if [ -f TEST1.TXT ]; then
echo "Test 1 output:"
cat TEST1.TXT
fi
if [ -f TEST2.TXT ]; then
echo "Test 2 output:"
cat TEST2.TXT
fi
if [ -f TEST3.TXT ]; then
echo "Test 3 output:"
cat TEST3.TXT
fi
exit 1
fi
# Verify test outputs
if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ] || [ ! -f TEST3.TXT ]; then
echo "Test output files missing"
exit 1
fi
# Check test results - looking for key format patterns
if ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST1.TXT || \
! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST2.TXT || \
! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST3.TXT; then
echo "Tests failed - unexpected output format"
echo "Test 1 output:"
cat TEST1.TXT
echo "Test 2 output:"
cat TEST2.TXT
echo "Test 3 output:"
cat TEST3.txt
exit 1
else
echo "All tests passed successfully"
echo "Test 1 output:"
cat TEST1.TXT
echo "Test 2 output:"
cat TEST2.TXT
echo "Test 3 output:"
cat TEST3.TXT
fi
- name: Move executable to upload directory
run: |
mkdir actions_upload
mv umskt.exe actions_upload/
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-DOS-x86-Compressed
path: actions_upload
path: build/actions_upload
+9 -9
View File
@@ -21,12 +21,12 @@
name: FreeBSD
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
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:
@@ -35,7 +35,7 @@
runs-on: ubuntu-latest
name: build-x86_64
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- name: Build & Test in FreeBSD
id: test
@@ -43,7 +43,7 @@
with:
usesh: true
prepare: |
pkg install -y cmake openssl git bash
pkg install -y cmake git bash
run: |
mkdir -p build
@@ -63,7 +63,7 @@
mv build/umskt build/actions_upload/umskt
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@v7
with:
name: UMSKT-FreeBSD
path: build/actions_upload
+9 -12
View File
@@ -46,7 +46,7 @@ jobs:
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout Source Tree
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Setup latest Alpine Linux
if: ${{ matrix.use_alpine }}
@@ -58,9 +58,6 @@ jobs:
cmake
git
musl-dev
openssl-dev
openssl-libs-static
zlib-dev
arch: ${{ matrix.arch }}
shell-name: alpine-target.sh
@@ -68,11 +65,11 @@ jobs:
if: ${{ !matrix.use_alpine }}
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake git libssl-dev zlib1g-dev
sudo apt-get install -y build-essential cmake git
- name: Configure and build UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
uses: threeal/cmake-action@v1
with:
options: MUSL_STATIC=ON CMAKE_POLICY_VERSION_MINIMUM=3.5
run-build: true
@@ -80,7 +77,7 @@ jobs:
- name: Configure and build UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
uses: threeal/cmake-action@v1
with:
options: MUSL_STATIC=ON CMAKE_POLICY_VERSION_MINIMUM=3.5
run-build: true
@@ -114,14 +111,14 @@ jobs:
mv build/umskt build/actions_upload/umskt
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@v7
with:
name: UMSKT-Linux-${{ matrix.arch }}-static
path: build/actions_upload
- name: Configure and build static internal deps UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
uses: threeal/cmake-action@v1
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF CMAKE_POLICY_VERSION_MINIMUM=3.5
run-build: true
@@ -129,7 +126,7 @@ jobs:
- name: Configure and build static internal deps UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
uses: threeal/cmake-action@v1
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF CMAKE_POLICY_VERSION_MINIMUM=3.5
run-build: true
@@ -159,7 +156,7 @@ jobs:
- name: Configure and build shared deps UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
uses: threeal/cmake-action@v1
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON CMAKE_POLICY_VERSION_MINIMUM=3.5
run-build: true
@@ -167,7 +164,7 @@ jobs:
- name: Configure and build shared deps UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
uses: threeal/cmake-action@v1
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON CMAKE_POLICY_VERSION_MINIMUM=3.5
run-build: true
+5 -30
View File
@@ -39,43 +39,18 @@ jobs:
- arch: arm64
steps:
- name: Checkout Source Tree
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Install Rosetta
if: matrix.arch == 'x86_64'
run: |
sudo softwareupdate --install-rosetta --agree-to-license || true
- name: Install Homebrew for x86_64
if: matrix.arch == 'x86_64'
env: { NONINTERACTIVE: 1 }
run: |
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- name: Install x86_64 OpenSSL
if: matrix.arch == 'x86_64'
run: |
arch -x86_64 /usr/local/bin/brew install openssl@3
echo "OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3" >> $GITHUB_ENV
echo "OPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@3/include" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/usr/local/opt/openssl@3/lib/pkgconfig" >> $GITHUB_ENV
- name: Install arm64 OpenSSL
if: matrix.arch == 'arm64'
run: |
brew install openssl@3
echo "OPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl@3" >> $GITHUB_ENV
echo "OPENSSL_INCLUDE_DIR=/opt/homebrew/opt/openssl@3/include" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/opt/homebrew/opt/openssl@3/lib/pkgconfig" >> $GITHUB_ENV
- name: Configure and build UMSKT
run: |
cd build
cmake -DCMAKE_BUILD_TYPE=Release .. \
-DCMAKE_OSX_ARCHITECTURES=${{matrix.arch}} \
-DOPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR \
-DOPENSSL_INCLUDE_DIR=$OPENSSL_INCLUDE_DIR \
-DOPENSSL_USE_STATIC_LIBS=TRUE \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
make
@@ -97,7 +72,7 @@ jobs:
./umskt -i 253286028742154311079061239762245184619981623171292574
- name: Upload platform-specific build
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@v7
with:
name: UMSKT-macOS-${{ matrix.arch }}
path: build/actions_upload
@@ -107,12 +82,12 @@ jobs:
runs-on: macos-latest
steps:
- name: Download x86_64 slice
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: UMSKT-macOS-x86_64
path: x86
- name: Download arm64 slice
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: UMSKT-macOS-arm64
path: arm
@@ -123,7 +98,7 @@ jobs:
lipo -create x86/umskt arm/umskt -output fat/umskt
lipo -info fat/umskt
- name: Upload universal build
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: UMSKT-macOS-universal
path: fat
+3 -57
View File
@@ -38,11 +38,9 @@ jobs:
include:
# - arch: arm32
# arch_compilename: amd64_arm
# vcpkg_arch: arm-windows-static
# cmake_arch: ARM
- arch: arm64
arch_compilename: amd64_arm64
vcpkg_arch: arm64-windows-static
cmake_arch: ARM64
steps:
- name: Setup MSVC for ${{ matrix.arch }}
@@ -51,57 +49,7 @@ jobs:
arch: ${{ matrix.arch_compilename }}
- name: Checkout Source Tree
uses: actions/checkout@v4
- name: Cache OpenSSL Binaries
uses: actions/cache/restore@v4
with:
path: |
${{ github.workspace }}-OpenSSL-MSVC-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Checkout and Compile OpenSSL v1.1.1
shell: pwsh
run: |
git clone https://github.com/UMSKT/openssl --branch OpenSSL_1_1_1-stable --depth 1 openssl-src
cd openssl-src
# Install Perl if needed
choco install strawberryperl -y
# Configure and build OpenSSL for ARM32
$env:PATH = "C:\Strawberry\perl\bin;$env:PATH"
# First set up Visual Studio environment
$vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
$vcvarsall = Join-Path $vsPath "VC\Auxiliary\Build\vcvarsall.bat"
$vcTarget = ""
if ("${{ matrix.arch}}" -eq "arm32") {
$vcTarget = "VC-WIN32-ARM"
} else {
$vcTarget = "VC-WIN64-ARM"
}
# Configure OpenSSL
perl Configure $vcTarget no-shared no-asm no-engine --prefix="$env:GITHUB_WORKSPACE/OpenSSL-MSVC-${{ matrix.arch }}"
# Build using MSVC ARM32 tools
cmd /c "call `"$vcvarsall`" ${{matrix.arch_compilename}} && nmake && nmake install_sw"
cd ..
- name: Save OpenSSL Binaries
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/OpenSSL-MSVC-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Set OpenSSL Environment
shell: pwsh
run: |
echo "OPENSSL_ROOT=$env:GITHUB_WORKSPACE/OpenSSL-MSVC-${{ matrix.arch }}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "OPENSSL_LIBDIR=lib" | Out-File -FilePath $env:GITHUB_ENV -Append
uses: actions/checkout@v7
- name: Configure UMSKT
shell: pwsh
@@ -109,8 +57,6 @@ jobs:
cmake -G "Visual Studio 18 2026" `
-A ${{ matrix.cmake_arch }} `
-DWINDOWS_ARM=ON `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }} `
-DCMAKE_POLICY_VERSION_MINIMUM="3.5" `
.
@@ -120,7 +66,7 @@ jobs:
cmake --build . --config Release
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@v7
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: Release/umskt.exe
@@ -134,7 +80,7 @@ jobs:
arch: [arm64]
steps:
- name: Download ARM64 artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: .
+31 -153
View File
@@ -61,85 +61,17 @@ jobs:
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
- name: Checkout Source Tree
uses: actions/checkout@v4
- name: Cache OpenSSL 1.1.1
uses: actions/cache/restore@v4
id: cache-openssl
with:
path: |
${{ github.workspace }}/OpenSSL-TDM-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Setup MSYS2
if: steps.cache-openssl.outputs.cache-hit != 'true'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.arch == 'x86' && 'MINGW32' || 'MINGW64' }}
update: true
install: >-
mingw-w64-${{ matrix.arch == 'x86' && 'i686' || 'x86_64' }}-gcc
mingw-w64-${{ matrix.arch == 'x86' && 'i686' || 'x86_64' }}-make
mingw-w64-x86_64-perl
perl
git
- name: Checkout and Compile OpenSSL 1.1.1
if: steps.cache-openssl.outputs.cache-hit != 'true'
shell: msys2 {0}
run: |
# Clone UMSKT's OpenSSL fork
echo "Cloning UMSKT OpenSSL fork..."
git clone https://github.com/UMSKT/openssl.git --branch OpenSSL_1_1_1-stable --depth 1 openssl-1.1.1
# Set up proper MSYS2 environment
export MSYS=winsymlinks:nativestrict
export MSYS2_PATH_TYPE=strict
export LANG=en_US.UTF-8
export PATH="/usr/bin:/mingw64/bin:$PATH"
export PATH="/c/TDM-GCC-64/bin:$PATH"
export MSYSTEM=${{ matrix.msystem }}
cd openssl-1.1.1
if [[ ${{ matrix.arch }} == "x86" ]]; then
/usr/bin/perl Configure mingw --prefix=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-${{ matrix.arch }} --openssldir=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-32 no-tests no-sse2 no-asm no-threads -DOPENSSL_DEV_NO_ATOMICS -mno-mmx -mno-sse -mno-sse2 -march=i686 -mtune=generic -Os -s -fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables -ffunction-sections -fdata-sections -fno-stack-protector
else
/usr/bin/perl Configure mingw64 --prefix=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-${{ matrix.arch }} --openssldir=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-64 no-tests no-asm -DOPENSSL_DEV_NO_ATOMICS -mno-mmx -Os -s -fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables -ffunction-sections -fdata-sections -fno-stack-protector
fi
mingw32-make -j
mingw32-make install_sw
cd ..
- name: Save OpenSSL 1.1.1
if: steps.cache-openssl.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/OpenSSL-TDM-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Set OpenSSL Environment
shell: pwsh
run: |
echo "OPENSSL_ROOT=$env:GITHUB_WORKSPACE/OpenSSL-TDM-${{ matrix.arch }}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "OPENSSL_LIBDIR=lib" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CMAKE_FLAGS=${{ matrix.cmake_flag }}" | Out-File -FilePath $env:GITHUB_ENV -Append
uses: actions/checkout@v7
- name: Configure UMSKT
shell: pwsh
run: |
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
$OPENSSL_ROOT = "$env:OPENSSL_ROOT"
$OPENSSL_LIB = "$OPENSSL_ROOT/$env:OPENSSL_LIBDIR"
$OPENSSL_INC = "$OPENSSL_ROOT/include"
cmake -G "MinGW Makefiles" `
-DCMAKE_C_COMPILER="gcc" `
-DCMAKE_CXX_COMPILER="g++" `
-DOPENSSL_ROOT_DIR="$OPENSSL_ROOT" `
-DOPENSSL_INCLUDE_DIR="$OPENSSL_INC" `
-DOPENSSL_CRYPTO_LIBRARY="$OPENSSL_LIB/libcrypto.a" `
-DOPENSSL_SSL_LIBRARY="$OPENSSL_LIB/libssl.a" `
-DCMAKE_C_FLAGS="$env:CMAKE_FLAGS" `
-DCMAKE_CXX_FLAGS="$env:CMAKE_FLAGS" `
-DCMAKE_C_FLAGS="${{ matrix.cmake_flag }}" `
-DCMAKE_CXX_FLAGS="${{ matrix.cmake_flag }}" `
-DCMAKE_POLICY_VERSION_MINIMUM="3.5" `
.
@@ -150,92 +82,38 @@ jobs:
mingw32-make
- name: Run tests
timeout-minutes: 2
shell: pwsh
run: |
$PSNativeCommandUseErrorActionPreference = $false
Write-Host Test 1 - generating key
.\umskt.exe -b 2C -c 365 -s 069420 -v
Write-Host Test 2 - generatng confid
.\umskt.exe -i 253286028742154311079061239762245184619981623171292574
$keyRaw = & .\umskt.exe -b 2C -c 365 -s 069420 2>&1 | Out-String
if ($LASTEXITCODE -ne 0) {
Write-Host "key generation exited ${LASTEXITCODE}: $keyRaw"
exit 1
}
$key = $keyRaw.Trim()
if ($key -notmatch '^[BCDFGHJKMPQRTVWXY2346789-]{29}$') {
Write-Host "key generation produced no key on stdout: [$key]"
exit 1
}
Write-Host Test 2 - validating that key
.\umskt.exe -b 2C -V $key
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Write-Host Test 3 - confirmation ID
$cidRaw = & .\umskt.exe -i 253286028742154311079061239762245184619981623171292574 2>&1 | Out-String
if ($LASTEXITCODE -ne 0) {
Write-Host "confirmation ID exited ${LASTEXITCODE}: $cidRaw"
exit 1
}
$cid = $cidRaw.Trim()
if ($cid -ne '020052-539422-707952-510766-409626-387731-998883') {
Write-Host "confirmation ID mismatch: [$cid]"
exit 1
}
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
uses: actions/upload-artifact@v7
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: umskt.exe
compress:
needs: build
if: success()
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- arch: x86
- arch: x64
steps:
- name: Setup TDM-GCC
run: |
Write-Host Downloading TDM-GCC v10.3.0...
Invoke-WebRequest -Uri 'https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe' -OutFile 'C:\Windows\temp\TDM-GCC-64.exe'
Write-Host Creating directory...
New-Item -ItemType Directory -Path 'C:\TDM-GCC-64'
Write-Host Copying files [Set 1/3]...
Start-Process '7z' -ArgumentList 'e C:\Windows\temp\TDM-GCC-64.exe -oC:\TDM-GCC-64 -y' -Wait
Write-Host Copying files [Set 2/3]...
Start-Process '7z' -ArgumentList 'e C:\TDM-GCC-64\*.tar.xz -oC:\TDM-GCC-64 -y' -Wait
Write-Host Copying files [Set 3/3]...
Start-Process '7z' -ArgumentList 'x C:\TDM-GCC-64\*.tar -oC:\TDM-GCC-64 -y' -Wait
Write-Host Adding environment variables...
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
- name: Setup UPX
run: |
Invoke-WebRequest -Uri 'https://github.com/upx/upx/releases/download/v5.0.2/upx-5.0.2-win64.zip' -OutFile 'C:\Windows\temp\upx.zip'
Write-Host Creating directory...
New-Item -ItemType Directory -Path 'C:\UPX'
Write-Host Copying files...
Expand-Archive -Path 'C:\Windows\temp\upx.zip' -DestinationPath 'C:\UPX'
Write-Host Adding environment variables...
$env:PATH = 'C:\UPX\upx-5.0.2-win64;' + $env:PATH
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
- name: Download ${{matrix.arch}} artifact
uses: actions/download-artifact@v4
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: .
- name: Compress binaries
shell: pwsh
run: |
# Strip symbols
strip .\umskt.exe
# Remove resources
llvm-objcopy --remove-section .rsrc umskt.exe umskt_comp.exe
# Compress with UPX
& "C:\UPX\upx-5.0.2-win64\upx.exe" --best --ultra-brute .\umskt_comp.exe
# Replace original EXE
Remove-Item .\umskt.exe
Rename-Item -Path .\umskt_comp.exe -NewName umskt.exe
- name: Run tests
shell: pwsh
run: |
Write-Host Test 1 - generating key `(BINK1998`)
.\umskt.exe -b 2C -c 365 -s 069420,999999 -v
Write-Host Test 2 - generating key `(BINK2002`)
.\umskt.exe -b 5A -c 640 -s 069420,999999 -v
Write-Host Test 3 - generatng confid
.\umskt.exe -i 253286028742154311079061239762245184619981623171292574
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-WinNT-${{ matrix.arch }}-Compressed
path: umskt.exe
path: umskt.exe
+151 -156
View File
@@ -41,8 +41,6 @@ if (WIN32 AND NOT MSVC)
# Match resource architecture with target architecture
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -F pe-i386 --target=pe-i386")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -mtune=generic -mno-sse -mno-sse2 -mno-mmx -mno-3dnow")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -mtune=generic -mno-sse -mno-sse2 -mno-mmx -mno-3dnow")
else()
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -F pe-x86-64 --target=pe-x86-64")
endif()
@@ -57,9 +55,8 @@ SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_OSX_SYSROOT "macosx" CACHE PATH "macOS SDK path")
OPTION(BUILD_SHARED_LIBS "Build internal libraries as dynamic" OFF)
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(DJGPP "Build the MS-DOS executable with DJGPP" OFF)
OPTION(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF)
OPTION(WINDOWS_ARM "Enable compilation for Windows on ARM (requires appropriate toolchain)" OFF)
@@ -71,21 +68,6 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
endif()
# neither does dos idk i'm trying random stuff
if (DJGPP_WATT32)
SET(UMSKT_USE_SHARED_OPENSSL ON)
endif()
IF(UMSKT_USE_SHARED_OPENSSL)
SET(OPENSSL_USE_STATIC_LIBS FALSE)
SET(OPENSSL_MSVC_STATIC_RT FALSE)
MESSAGE(STATUS "[UMSKT] Requesting dynamic version of OpenSSL")
ELSE()
SET(OPENSSL_USE_STATIC_LIBS TRUE)
SET(OPENSSL_MSVC_STATIC_RT TRUE)
MESSAGE(STATUS "[UMSKT] Requesting static version of OpenSSL")
ENDIF()
# Configure ARM-specific settings if enabled
if (WINDOWS_ARM)
if (MSVC)
@@ -103,18 +85,17 @@ if (WINDOWS_ARM)
message(STATUS "[UMSKT] Configuring for Windows on ARM")
endif()
IF(DJGPP_WATT32)
IF(DJGPP)
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)
# Maximum compatibility flags for DOS/NTVDM
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
# The DOS workflow has no CMAKE_BUILD_TYPE, so without an explicit -O the
# i386 binary is unoptimized and DOSBox 0.74 cannot finish key generation
# inside its 30 second timeout.
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
MESSAGE(STATUS "[UMSKT] Using i386 target for DOS DGJPP with stub: ${CWSDSTUB_LOCATION}")
ENDIF()
@@ -136,14 +117,11 @@ IF(MSVC)
ENDIF()
SET(CMAKE_EXE_LINKER_FLAGS "/INCREMENTAL:NO /NODEFAULTLIB:MSVCRT /OPT:REF /OPT:ICF")
SET(CMAKE_ENABLE_EXPORTS ON)
SET(UMSKT_EXE_WINDOWS_EXTRA src/windows/umskt.rc)
SET(UMSKT_EXE_WINDOWS_DLL src/windows/dllmain.cpp)
ENDIF()
IF(MUSL_STATIC)
MESSAGE(STATUS "[UMSKT] Performing a fully static build using muslc")
SET(BUILD_SHARED_LIBS OFF)
SET(OPENSSL_USE_STATIC_LIBS TRUE)
SET(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
SET(CMAKE_SHARED_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
@@ -152,150 +130,167 @@ IF(MUSL_STATIC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
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()
# MinGW on Windows is one freestanding pipeline, compiled -m32 and -m64.
# x86 is the Windows 98 / NT 4.0 PE. x64 uses the same kernel32-only link.
# Every other target uses the same sources with the platform C library.
if (WIN32 AND NOT MSVC AND NOT DJGPP)
SET(UMSKT_FREESTANDING ON)
endif()
IF(NOT MUSL_STATIC)
# if we found shared libraries - do the following:
IF (OPENSSL_USE_STATIC_LIBS)
MESSAGE(STATUS "[UMSKT] requested static version of OpenSSL")
if (NOT UMSKT_USE_SHARED_OPENSSL)
MESSAGE(STATUS "[UMSKT] not asked for shared version of OpenSSL")
ENDIF()
IF(MSVC)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "ws2_32.lib")
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "crypt32.lib")
MESSAGE(STATUS "[UMSKT] msvc adding ws2_32.lib crypt32.lib")
ENDIF()
ENDIF()
STRING(REGEX MATCH "(\\.so|\\.dll|\\.dylib)$" OPENSSL_CRYPTO_SHARED "${OPENSSL_CRYPTO_LIBRARY}")
IF(OPENSSL_CRYPTO_SHARED)
MESSAGE(STATUS "[UMSKT] Detected Shared library version of OpenSSL")
ELSE()
MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL")
# static libcrypto on Fedora needs -lz at link time
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
FIND_PACKAGE(ZLIB REQUIRED)
IF (NOT ZLIB_FOUND)
MESSAGE(FATAL_ERROR "[UMSKT] linux static OpenSSL requires zlib")
ENDIF()
ENDIF()
ENDIF()
ENDIF()
# initalize cpm.CMake
INCLUDE(cmake/CPM.cmake)
# fetch cpm.CMake dependencies
# Include JSON development library
CPMAddPackage(
NAME nlohmann_json
GITHUB_REPOSITORY nlohmann/json
VERSION 3.11.2
set(UMSKT_KEYS_EMBED "${CMAKE_BINARY_DIR}/keys_embed.cpp")
add_custom_command(
OUTPUT "${UMSKT_KEYS_EMBED}"
COMMAND ${CMAKE_COMMAND} -DINPUT=${CMAKE_SOURCE_DIR}/keys.json -DOUTPUT=${UMSKT_KEYS_EMBED} -P ${CMAKE_SOURCE_DIR}/cmake/embed_keys.cmake
DEPENDS "${CMAKE_SOURCE_DIR}/keys.json" "${CMAKE_SOURCE_DIR}/cmake/embed_keys.cmake"
VERBATIM
)
# Include fmt development library
CPMAddPackage(
NAME fmt
GITHUB_REPOSITORY fmtlib/fmt
GIT_TAG 10.0.0
VERSION 10.0.0
#OPTIONS "FMT_INSTALL YES" "BUILD_SHARED_LIBS OFF"
set(UMSKT_SOURCES
src/cli.cpp
src/windows/json.cpp
${UMSKT_KEYS_EMBED}
src/crypto/mini_bn.cpp
src/crypto/mini_ec.cpp
src/crypto/mini_rand.cpp
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
)
# Include cmrc resource compiler
CPMAddPackage(
NAME cmrc
GITHUB_REPOSITORY vector-of-bool/cmrc
GIT_TAG 2.0.1
VERSION 2.0.1
)
if (UMSKT_FREESTANDING)
list(APPEND UMSKT_SOURCES src/windows/crt_win32.cpp src/windows/umskt.rc)
elseif (WIN32)
list(APPEND UMSKT_SOURCES src/windows/umskt.rc)
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"
#)
add_executable(umskt ${UMSKT_SOURCES})
#include googletest unit testing library
#CPMAddPackage(
# NAME googletest
# GITHUB_REPOSITORY google/googletest
# VERSION 1.13.0
# OPTIONS "INSTALL_GTEST OFF" "gtest_force_shared_crt"
#)
if (UMSKT_FREESTANDING)
set(CMAKE_C_STANDARD_LIBRARIES "")
set(CMAKE_CXX_STANDARD_LIBRARIES "")
### 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)
#### 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")
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()
ADD_LIBRARY(_umskt ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_DIRECTORIES(_umskt PUBLIC ${UMSKT_LINK_DIRS})
TARGET_LINK_LIBRARIES(_umskt ${OPENSSL_CRYPTO_LIBRARIES} fmt ${UMSKT_LINK_LIBS})
### UMSKT executable compilation
ADD_EXECUTABLE(umskt src/main.cpp src/cli.cpp ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(umskt _umskt ${OPENSSL_CRYPTO_LIBRARIES} ${ZLIB_LIBRARIES} fmt nlohmann_json::nlohmann_json umskt::rc ${UMSKT_LINK_LIBS})
TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS})
# Link required Windows system libraries for OpenSSL
if (WIN32)
target_link_libraries(umskt crypt32 ws2_32)
set(UMSKT_WIN_X86 OFF)
if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR CMAKE_C_FLAGS MATCHES "(^| )-m32( |$)" OR CMAKE_CXX_FLAGS MATCHES "(^| )-m32( |$)")
set(UMSKT_WIN_X86 ON)
endif()
IF(MSVC AND MSVC_MSDOS_STUB)
SET_PROPERTY(TARGET umskt APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB})
ENDIF()
set(UMSKT_FREE_FLAGS
-ffreestanding
-fno-exceptions
-fno-rtti
-fno-threadsafe-statics
-fno-use-cxa-atexit
-fno-stack-protector
-fno-unwind-tables
-fno-asynchronous-unwind-tables
-fno-tree-vectorize
-fno-tree-loop-distribute-patterns
)
if (UMSKT_WIN_X86)
list(APPEND UMSKT_FREE_FLAGS
-m32
-march=pentium
-mtune=pentium
-mfpmath=387
-mno-mmx
-mno-sse
-mno-sse2
-mno-3dnow
)
set(UMSKT_WIN_ARCH x86)
else()
list(APPEND UMSKT_FREE_FLAGS -m64)
set(UMSKT_WIN_ARCH x64)
endif()
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install(TARGETS umskt DESTINATION bin)
ENDIF()
target_compile_options(umskt PRIVATE ${UMSKT_FREE_FLAGS})
target_compile_definitions(umskt PRIVATE
UMSKT_FREESTANDING
WINVER=0x0400
_WIN32_WINNT=0x0400
NTDDI_VERSION=0x04000000
NDEBUG
)
if (UMSKT_WIN_X86)
target_link_options(umskt PRIVATE
-m32
-nostdlib
-nostartfiles
-nodefaultlibs
-Wl,--disable-auto-import
-Wl,--gc-sections
-Wl,--subsystem,console:4.0
-Wl,--major-os-version,4
-Wl,--minor-os-version,0
-Wl,--major-subsystem-version,4
-Wl,--minor-subsystem-version,0
"SHELL:-Xlinker --stack -Xlinker 1048576,4096"
-Wl,-e,_mainCRTStartup
-Wl,--defsym,__init_array_start=0
-Wl,--defsym,__init_array_end=0
)
else()
target_link_options(umskt PRIVATE
-m64
-nostdlib
-nostartfiles
-nodefaultlibs
-Wl,--disable-auto-import
-Wl,--gc-sections
-Wl,--subsystem,console:5.2
-Wl,--major-os-version,5
-Wl,--minor-os-version,2
-Wl,--major-subsystem-version,5
-Wl,--minor-subsystem-version,2
"SHELL:-Xlinker --stack -Xlinker 1048576,4096"
-Wl,-e,mainCRTStartup
-Wl,--defsym,__init_array_start=0
-Wl,--defsym,__init_array_end=0
)
endif()
target_link_libraries(umskt PRIVATE kernel32)
### 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()
IF (DJGPP_WATT32)
get_filename_component(UMSKT_GCC_BIN "${CMAKE_CXX_COMPILER}" DIRECTORY)
find_program(UMSKT_OBJDUMP NAMES objdump HINTS "${UMSKT_GCC_BIN}")
if (UMSKT_OBJDUMP)
add_custom_command(TARGET umskt POST_BUILD
COMMAND powershell.exe -NoProfile -ExecutionPolicy Bypass -File "${CMAKE_SOURCE_DIR}/tools/check-win-baseline.ps1" -Exe "$<TARGET_FILE:umskt>" -Objdump "${UMSKT_OBJDUMP}" -Arch "${UMSKT_WIN_ARCH}"
COMMENT "Checking umskt for a kernel32-only import table"
VERBATIM
)
endif()
message(STATUS "[UMSKT] Freestanding Windows ${UMSKT_WIN_ARCH} (kernel32 only)")
else()
if (DJGPP)
message(STATUS "[UMSKT] Configuring DJGPP post-build commands")
# Set .exe suffix for DJGPP builds
set_target_properties(umskt PROPERTIES SUFFIX ".exe")
add_custom_command(TARGET umskt POST_BUILD
# Convert exe to coff, removing the default stub
add_custom_command(TARGET umskt POST_BUILD
COMMAND ${DJGPP_BIN_LOCATION}/exe2coff $<TARGET_FILE:umskt>
# Concatenate CWSDSTUB with the COFF file
COMMAND ${CMAKE_COMMAND} -E cat ${CWSDSTUB_LOCATION} $<TARGET_FILE_DIR:umskt>/umskt > $<TARGET_FILE:umskt>
# Clean up the COFF file
COMMAND ${CMAKE_COMMAND} -E rm $<TARGET_FILE_DIR:umskt>/umskt
)
message(STATUS "[UMSKT] STUBIFY_LOCATION set to: ${STUBIFY_LOCATION}")
message(STATUS "[UMSKT] CWSDSTUB_LOCATION set to: ${CWSDSTUB_LOCATION}")
message(STATUS "[UMSKT] DJGPP_BIN_LOCATION set to: ${DJGPP_BIN_LOCATION}")
ENDIF()
ENDIF()
endif()
if (MSVC AND MSVC_MSDOS_STUB)
set_property(TARGET umskt APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB})
endif()
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install(TARGETS umskt DESTINATION bin)
endif()
if (EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".html")
set_target_properties(umskt PROPERTIES COMPILE_FLAGS "-Os")
set_target_properties(umskt PROPERTIES LINK_FLAGS "-Os -sWASM=1")
endif()
message(STATUS "[UMSKT] Hosted build using the bundled curve code")
endif()
+1 -3
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
+5 -36
View File
@@ -67,54 +67,23 @@ RUN git clone https://github.com/andrewwutw/build-djgpp.git djgpp \
&& ./build-djgpp.sh $BUILD_VER \
&& rm -rf /tmp/djgpp
# Stage 3: compile watt32 for djgpp-i386
FROM djgpp as watt32
WORKDIR /djgpp
ENV WATT_ROOT=/djgpp/watt32 DJGPP_PREFIX=i386-pc-msdosdjgpp
SHELL ["/bin/bash", "-c"]
RUN git clone https://github.com/gvanem/Watt-32.git watt32 \
&& cd watt32/util \
&& make clean && make linux \
&& cd ../src \
&& source /djgpp/setenv \
&& ./configur.sh djgpp \
&& sed -i 's/i586/i386/g' djgpp.mak \
&& wget https://gist.github.com/Neo-Desktop/ad26e888d64b22a59c743ab4e21ac186/raw/c9a73e1eb75ba8857883ac5c08691d2fe5b82594/djgpp.err -O ../inc/sys/djgpp.err \
&& wget https://gist.github.com/Neo-Desktop/ad26e888d64b22a59c743ab4e21ac186/raw/c9a73e1eb75ba8857883ac5c08691d2fe5b82594/syserr.c -O build/djgpp/syserr.c \
&& make -f djgpp.mak \
&& ln -s /djgpp/watt32/lib/libwatt.a /djgpp/lib
# Stage 4: compile OpenSSL for djgpp-i386/watt32
FROM watt32 as openssl
WORKDIR /tmp
SHELL ["/bin/bash", "-c"]
RUN git clone https://github.com/openssl/openssl.git openssl \
&& cd openssl \
&& git checkout openssl-3.1.1 \
&& source /djgpp/setenv \
&& wget https://gist.github.com/Neo-Desktop/ad26e888d64b22a59c743ab4e21ac186/raw/c9a73e1eb75ba8857883ac5c08691d2fe5b82594/50-djgpp.conf.patch -O Configurations/50-djgpp.conf.patch \
&& git apply Configurations/50-djgpp.conf.patch \
&& ./Configure no-threads -DOPENSSL_DEV_NO_ATOMICS --prefix=/djgpp DJGPP \
&& make && make install
# Stage 5: compile UMSKT
FROM openssl as build
# Stage 3: compile UMSKT
FROM djgpp as build
WORKDIR /src
COPY . /src
ENV CC=/djgpp/bin/i386-pc-msdosdjgpp-gcc CXX=/djgpp/bin/i386-pc-msdosdjgpp-g++ PKG_CONFIG_PATH=/djgpp/lib/pkgconfig VERBOSE=1
ENV CC=/djgpp/bin/i386-pc-msdosdjgpp-gcc CXX=/djgpp/bin/i386-pc-msdosdjgpp-g++ VERBOSE=1
SHELL ["/bin/bash", "-c"]
# Build UMSKT from the local directory
RUN mkdir /src/build \
&& cd /src/build \
&& source /djgpp/setenv \
&& cmake -DDJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a .. \
&& cmake -DDJGPP=ON .. \
&& make
CMD ["bash"]
# Stage 6: Output
# Stage 4: Output
FROM scratch as output
COPY --from=build /src/build/umskt.exe /umskt.exe
+2 -25
View File
@@ -18,31 +18,8 @@
# @FileCreated by Neo on 06/25/2023
# @Maintainer Neo
# Stage 1: Install Prerequisites
FROM emscripten/emsdk:latest as prerequisites
RUN apt update \
&& apt -y install pkg-config \
&& apt -y clean autoclean autoremove
# Stage 2: compile OpenSSL for emscripten
FROM prerequisites as openssl
WORKDIR /tmp
ENV EMSCRIPTEN=/emsdk/upstream/emscripten VERBOSE=1
RUN git clone https://github.com/openssl/openssl.git openssl \
&& cd openssl \
&& git checkout openssl-3.1.1 \
&& emconfigure ./Configure gcc -no-tests -no-asm -static -fPIC -no-sock -no-afalgeng -DOPENSSL_SYS_NETWARE -DSIG_DFL=0 -DSIG_IGN=0 -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 --with-rand-seed=getrandom --prefix=$EMSCRIPTEN/cache/sysroot|| exit $? \
&& sed -i 's|^CROSS_COMPILE.*$|CROSS_COMPILE=|g' Makefile \
&& emmake make -j 12 build_generated libssl.a libcrypto.a build_libs_nodep \
&& rm -rf $EMSCRIPTEN/cache/sysroot/include/openssl \
&& cp -R include/openssl $EMSCRIPTEN/cache/sysroot/include \
&& cp libcrypto.a libssl.a $EMSCRIPTEN/cache/sysroot/lib \
&& cp libcrypto.pc libssl.pc openssl.pc $EMSCRIPTEN/cache/sysroot/lib/pkgconfig/ \
&& cd .. \
&& rm -rf openssl
# Stage 3: compile UMSKT
FROM openssl as build
# Stage 1: compile UMSKT
FROM emscripten/emsdk:latest as build
WORKDIR /src
COPY . /src
-11
View File
@@ -40,16 +40,6 @@ 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\
@@ -67,7 +57,6 @@ 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 && `
+9 -10
View File
@@ -19,7 +19,7 @@
| [![Windows ARM](https://github.com/UMSKT/UMSKT/actions/workflows/windows-arm.yml/badge.svg)](../../actions/workflows/windows-arm.yml) |
| [![macOS](https://github.com/UMSKT/UMSKT/actions/workflows/macos.yml/badge.svg)](../../actions/workflows/macos.yml) |
| [![Linux](https://github.com/UMSKT/UMSKT/actions/workflows/linux.yml/badge.svg)](../../actions/workflows/linux.yml) |
| [![FreeBSD](https://img.shields.io/badge/FreeBSD-unmaintained-D3D3D3?logo=github)](../../actions/workflows/freebsd.yml) |
| [![FreeBSD](https://github.com/UMSKT/UMSKT/actions/workflows/freebsd.yml/badge.svg)](../../actions/workflows/freebsd.yml) |
| [![DOS DJGPP](https://github.com/UMSKT/UMSKT/actions/workflows/dos-djgpp.yml/badge.svg)](../../actions/workflows/dos-djgpp.yml) |
------
@@ -54,18 +54,17 @@ In light of the recent exponential interest in this project I've decided to put
* MS-DOS 6.22 or later
* Any DOS-based version of Windows
* Windows NT 4.0 or later (via NTVDM)
#### Windows (x86/x64)
* i686 processor or better
* Windows XP or later
> [!WARNING]
> Processors barely meeting the minimum system requirements for XP may not work. Use the MS-DOS version via NTVDM in that case.
#### Windows (x86)
* Pentium processor or better
* Windows 98 First Edition or later
* Windows NT 4.0 SP6a or later
#### Windows (x64)
* Windows MT 5.2 (Windows XP x64, Windows Server 2003) or later
#### Windows (ARM64)
* Windows 11 21H2 or later
* Winodws 11 21H2 or later
#### macOS
* Apple Silicon or x86_64 processor
* Latest version of macOS
* macOS 26 Tahoe or later
#### Linux
* modern ARM, x86, or x86_64 processor
* Latest version of your Linux distro
-33
View File
@@ -1,33 +0,0 @@
set(CPM_DOWNLOAD_VERSION 0.38.1)
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
function(download_cpm)
message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}")
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION}
)
endfunction()
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
download_cpm()
else()
# resume download if it previously failed
file(READ ${CPM_DOWNLOAD_LOCATION} check)
if("${check}" STREQUAL "")
download_cpm()
endif()
unset(check)
endif()
include(${CPM_DOWNLOAD_LOCATION})
+10
View File
@@ -0,0 +1,10 @@
if(NOT DEFINED INPUT OR NOT DEFINED OUTPUT)
message(FATAL_ERROR "embed_keys.cmake requires -DINPUT= and -DOUTPUT=")
endif()
file(READ "${INPUT}" KEYS)
file(WRITE "${OUTPUT}" [=[extern const char umskt_keys_json[] = R"UMSKTJSON(
]=] "${KEYS}" [=[
)UMSKTJSON";
extern const int umskt_keys_json_size = (int)(sizeof(umskt_keys_json) - 1);
]=])
+904 -602
View File
File diff suppressed because it is too large. Load diff
-110
View File
@@ -1,110 +0,0 @@
/**
* This file is a part of the UMSKT Project
*
* Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 6/6/2023
* @Maintainer Neo
*/
#ifndef UMSKT_CLI_H
#define UMSKT_CLI_H
#include "header.h"
#include <cmrc/cmrc.hpp>
#include "libumskt/libumskt.h"
#include "libumskt/pidgen2/PIDGEN2.h"
#include "libumskt/pidgen3/PIDGEN3.h"
#include "libumskt/pidgen3/BINK1998.h"
#include "libumskt/pidgen3/BINK2002.h"
#include "libumskt/confid/confid.h"
CMRC_DECLARE(umskt);
enum ACTIVATION_ALGORITHM {
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
OFFICE_ACC = 5,
};
enum MODE {
MODE_BINK1998_GENERATE = 0,
MODE_BINK2002_GENERATE = 1,
MODE_CONFIRMATION_ID = 2,
MODE_BINK1998_VALIDATE = 3,
MODE_BINK2002_VALIDATE = 4,
};
struct Options {
std::string binkid;
std::string keysFilename;
std::string instid;
std::string keyToCheck;
std::string productid;
int channelID;
int serialMin;
int serialMax;
int numKeys;
bool upgrade;
bool serialSet;
bool verbose;
bool help;
bool error;
bool list;
bool nonewlines;
bool overrideVersion;
bool nodashes;
MODE applicationMode;
ACTIVATION_ALGORITHM activationMode;
};
class CLI {
Options options;
json keys;
const char* BINKID;
BIGNUM *privateKey, *genOrder;
EC_POINT *genPoint, *pubPoint;
EC_GROUP *eCurve;
char pKey[25];
int count, total;
public:
CLI(Options options, json keys);
~CLI();
static bool loadJSON(const fs::path& filename, json *output);
static void showHelp(char *argv[]);
static int parseCommandLine(int argc, char* argv[], Options *options);
static int validateCommandLine(Options* options, char *argv[], json *keys);
static void printID(DWORD *pid);
void printKey(char *pk);
static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
static std::string readFromStdin();
int BINK1998Generate();
int BINK2002Generate();
int BINK1998Validate();
int BINK2002Validate();
int ConfirmationID();
};
#endif //UMSKT_CLI_H
File diff suppressed because it is too large. Load diff
+618
View File
@@ -0,0 +1,618 @@
/* This file is a part of the UMSKT Project.
*
* Copyleft (C) 2019-2026 UMSKT Contributors (et.al.)
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* Short Weierstrass curves over a prime field. Scalar multiplication uses
* Jacobian coordinates so a 384/512-bit multiply does one inversion.
*/
#include "mini_openssl.h"
#include <stdlib.h>
#include <string.h>
struct ec_group_st {
BIGNUM *p;
BIGNUM *a;
BIGNUM *b;
};
struct ec_point_st {
const EC_GROUP *group;
BIGNUM *x;
BIGNUM *y;
int infinity;
};
struct jpoint {
BIGNUM *X;
BIGNUM *Y;
BIGNUM *Z;
int infinity;
};
static int field_mul(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
return BN_mod_mul(r, a, b, g->p, NULL);
}
static int field_sqr(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a) {
return BN_mod_sqr(r, a, g->p, NULL);
}
static int field_add(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
return BN_mod_add(r, a, b, g->p, NULL);
}
static int field_sub(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
return BN_mod_sub(r, a, b, g->p, NULL);
}
static int field_reduce(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a) {
BIGNUM *zero = BN_new();
int ok;
if (!zero) {
return 0;
}
BN_zero(zero);
ok = BN_mod_add(r, a, zero, g->p, NULL);
BN_free(zero);
return ok;
}
static int field_mul_small(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a, BN_ULONG w) {
BIGNUM *tmp = BN_dup(a);
int ok = tmp && BN_mul_word(tmp, w) && field_reduce(g, r, tmp);
BN_free(tmp);
return ok;
}
static int field_inv(const EC_GROUP *g, BIGNUM *r, const BIGNUM *a) {
return BN_mod_inverse(r, a, g->p);
}
static void jfree(struct jpoint *p) {
if (!p) {
return;
}
BN_free(p->X);
BN_free(p->Y);
BN_free(p->Z);
}
static int jinit(struct jpoint *p) {
p->X = BN_new();
p->Y = BN_new();
p->Z = BN_new();
p->infinity = 1;
if (!p->X || !p->Y || !p->Z) {
jfree(p);
return 0;
}
return 1;
}
static int jset_affine(const EC_GROUP *g, struct jpoint *p, const EC_POINT *src) {
if (src->infinity) {
p->infinity = 1;
return 1;
}
p->infinity = 0;
return field_reduce(g, p->X, src->x) && field_reduce(g, p->Y, src->y) && BN_set_word(p->Z, 1);
}
static int jdouble(const EC_GROUP *g, struct jpoint *p) {
BIGNUM *YY;
BIGNUM *YYYY;
BIGNUM *XX;
BIGNUM *S;
BIGNUM *M;
BIGNUM *Z2;
BIGNUM *Z4;
BIGNUM *X3;
BIGNUM *Y3;
BIGNUM *Z3;
BIGNUM *tmp;
int ok;
if (p->infinity) {
return 1;
}
if (BN_is_zero(p->Y)) {
p->infinity = 1;
return 1;
}
YY = BN_new();
YYYY = BN_new();
XX = BN_new();
S = BN_new();
M = BN_new();
Z2 = BN_new();
Z4 = BN_new();
X3 = BN_new();
Y3 = BN_new();
Z3 = BN_new();
tmp = BN_new();
ok = YY && YYYY && XX && S && M && Z2 && Z4 && X3 && Y3 && Z3 && tmp;
if (ok) {
ok = field_sqr(g, YY, p->Y) && field_sqr(g, YYYY, YY) && field_sqr(g, XX, p->X);
}
if (ok) {
ok = field_mul(g, S, p->X, YY) && field_mul_small(g, S, S, 4);
}
if (ok) {
ok = field_mul_small(g, M, XX, 3) && field_sqr(g, Z2, p->Z) && field_sqr(g, Z4, Z2) && field_mul(g, tmp, g->a, Z4) && field_add(g, M, M, tmp);
}
if (ok) {
ok = field_sqr(g, X3, M) && field_mul_small(g, tmp, S, 2) && field_sub(g, X3, X3, tmp);
}
if (ok) {
ok = field_mul(g, Z3, p->Y, p->Z) && field_mul_small(g, Z3, Z3, 2);
}
if (ok) {
ok = field_sub(g, tmp, S, X3) && field_mul(g, tmp, M, tmp) && field_mul_small(g, YYYY, YYYY, 8) && field_sub(g, Y3, tmp, YYYY);
}
if (ok) {
ok = BN_copy(p->X, X3) && BN_copy(p->Y, Y3) && BN_copy(p->Z, Z3);
}
BN_free(YY);
BN_free(YYYY);
BN_free(XX);
BN_free(S);
BN_free(M);
BN_free(Z2);
BN_free(Z4);
BN_free(X3);
BN_free(Y3);
BN_free(Z3);
BN_free(tmp);
return ok;
}
static int jadd_mixed(const EC_GROUP *g, struct jpoint *p, const EC_POINT *q) {
BIGNUM *Z2;
BIGNUM *Z3;
BIGNUM *U2;
BIGNUM *S2;
BIGNUM *H;
BIGNUM *R;
BIGNUM *HH;
BIGNUM *HHH;
BIGNUM *U1HH;
BIGNUM *X3;
BIGNUM *Y3;
BIGNUM *Zout;
BIGNUM *tmp;
int ok;
if (q->infinity) {
return 1;
}
if (p->infinity) {
return jset_affine(g, p, q);
}
Z2 = BN_new();
Z3 = BN_new();
U2 = BN_new();
S2 = BN_new();
H = BN_new();
R = BN_new();
HH = BN_new();
HHH = BN_new();
U1HH = BN_new();
X3 = BN_new();
Y3 = BN_new();
Zout = BN_new();
tmp = BN_new();
ok = Z2 && Z3 && U2 && S2 && H && R && HH && HHH && U1HH && X3 && Y3 && Zout && tmp;
if (ok) {
ok = field_sqr(g, Z2, p->Z) && field_mul(g, Z3, Z2, p->Z) && field_mul(g, U2, q->x, Z2) && field_mul(g, S2, q->y, Z3);
}
if (ok) {
ok = field_sub(g, H, U2, p->X) && field_sub(g, R, S2, p->Y);
}
if (ok && BN_is_zero(H)) {
int double_it = BN_is_zero(R);
BN_free(Z2);
BN_free(Z3);
BN_free(U2);
BN_free(S2);
BN_free(H);
BN_free(R);
BN_free(HH);
BN_free(HHH);
BN_free(U1HH);
BN_free(X3);
BN_free(Y3);
BN_free(Zout);
BN_free(tmp);
if (double_it) {
return jdouble(g, p);
}
p->infinity = 1;
return 1;
}
if (ok) {
ok = field_sqr(g, HH, H) && field_mul(g, HHH, H, HH) && field_mul(g, U1HH, p->X, HH);
}
if (ok) {
ok = field_sqr(g, X3, R) && field_sub(g, X3, X3, HHH) && field_mul_small(g, tmp, U1HH, 2) && field_sub(g, X3, X3, tmp);
}
if (ok) {
ok = field_sub(g, tmp, U1HH, X3) && field_mul(g, tmp, R, tmp) && field_mul(g, Y3, p->Y, HHH) && field_sub(g, Y3, tmp, Y3);
}
if (ok) {
ok = field_mul(g, Zout, p->Z, H) && BN_copy(p->X, X3) && BN_copy(p->Y, Y3) && BN_copy(p->Z, Zout);
}
BN_free(Z2);
BN_free(Z3);
BN_free(U2);
BN_free(S2);
BN_free(H);
BN_free(R);
BN_free(HH);
BN_free(HHH);
BN_free(U1HH);
BN_free(X3);
BN_free(Y3);
BN_free(Zout);
BN_free(tmp);
return ok;
}
static int jto_affine(const EC_GROUP *g, EC_POINT *out, const struct jpoint *p) {
BIGNUM *inv = BN_new();
BIGNUM *z2 = BN_new();
BIGNUM *z3 = BN_new();
int ok = inv && z2 && z3;
if (p->infinity || BN_is_zero(p->Z)) {
out->infinity = 1;
BN_free(inv);
BN_free(z2);
BN_free(z3);
return 1;
}
if (ok) {
ok = field_inv(g, inv, p->Z) && field_sqr(g, z2, inv) && field_mul(g, z3, z2, inv) && field_mul(g, out->x, p->X, z2) && field_mul(g, out->y, p->Y, z3);
}
if (ok) {
out->infinity = 0;
}
BN_free(inv);
BN_free(z2);
BN_free(z3);
return ok;
}
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
EC_GROUP *group;
(void)ctx;
if (!p || BN_is_zero(p)) {
return NULL;
}
group = (EC_GROUP *)malloc(sizeof(EC_GROUP));
if (!group) {
return NULL;
}
group->p = BN_dup(p);
group->a = BN_dup(a);
group->b = BN_dup(b);
if (!group->p || !group->a || !group->b) {
EC_GROUP_free(group);
return NULL;
}
return group;
}
void EC_GROUP_free(EC_GROUP *group) {
if (!group) {
return;
}
BN_free(group->p);
BN_free(group->a);
BN_free(group->b);
free(group);
}
EC_POINT *EC_POINT_new(const EC_GROUP *group) {
EC_POINT *point = (EC_POINT *)malloc(sizeof(EC_POINT));
if (!point) {
return NULL;
}
point->group = group;
point->x = BN_new();
point->y = BN_new();
point->infinity = 1;
if (!point->x || !point->y) {
EC_POINT_free(point);
return NULL;
}
return point;
}
void EC_POINT_free(EC_POINT *point) {
if (!point) {
return;
}
BN_free(point->x);
BN_free(point->y);
free(point);
}
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) {
(void)ctx;
if (!group || !point || !x || !y) {
return 0;
}
point->group = group;
point->infinity = 0;
return field_reduce(group, point->x, x) && field_reduce(group, point->y, y);
}
int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) {
(void)group;
(void)ctx;
if (!point || point->infinity) {
return 0;
}
return BN_copy(x, point->x) && BN_copy(y, point->y);
}
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) {
BIGNUM *y2 = BN_new();
BIGNUM *x3 = BN_new();
BIGNUM *ax = BN_new();
BIGNUM *rhs = BN_new();
int ok;
(void)ctx;
if (!point || point->infinity) {
BN_free(y2);
BN_free(x3);
BN_free(ax);
BN_free(rhs);
return 0;
}
ok = y2 && x3 && ax && rhs && field_sqr(group, y2, point->y) && field_sqr(group, x3, point->x) && field_mul(group, x3, x3, point->x) && field_mul(group, ax, group->a, point->x) && field_add(group, rhs, x3, ax) && field_add(group, rhs, rhs, group->b);
if (ok) {
ok = BN_ucmp(y2, rhs) == 0;
}
BN_free(y2);
BN_free(x3);
BN_free(ax);
BN_free(rhs);
return ok;
}
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) {
struct jpoint sum;
int ok;
(void)ctx;
if (!jinit(&sum)) {
return 0;
}
ok = jset_affine(group, &sum, a) && jadd_mixed(group, &sum, b) && jto_affine(group, r, &sum);
jfree(&sum);
return ok;
}
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx) {
struct jpoint acc;
int bits;
int i;
int ok;
(void)ctx;
if (n) {
return 0;
}
if (!q || !m) {
return 0;
}
if (q->infinity || BN_is_zero(m)) {
r->infinity = 1;
return 1;
}
if (!jinit(&acc)) {
return 0;
}
bits = BN_num_bits(m);
ok = 1;
for (i = bits - 1; ok && i >= 0; i--) {
if (!acc.infinity) {
ok = jdouble(group, &acc);
}
if (ok && BN_is_bit_set(m, i)) {
ok = jadd_mixed(group, &acc, q);
}
}
if (ok) {
ok = jto_affine(group, r, &acc);
}
jfree(&acc);
return ok;
}
unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md) {
uint32_t h0 = 0x67452301u;
uint32_t h1 = 0xEFCDAB89u;
uint32_t h2 = 0x98BADCFEu;
uint32_t h3 = 0x10325476u;
uint32_t h4 = 0xC3D2E1F0u;
size_t bit_len_hi;
size_t bit_len_lo;
size_t total;
size_t offset = 0;
unsigned char block[64];
size_t i;
if (!md) {
return NULL;
}
bit_len_lo = (n << 3) & 0xFFFFFFFFu;
bit_len_hi = (n >> 29);
while (offset + 64 <= n) {
uint32_t w[80];
uint32_t a, b, c, e, f, temp;
uint32_t k;
for (i = 0; i < 16; i++) {
w[i] = ((uint32_t)d[offset + i * 4] << 24) | ((uint32_t)d[offset + i * 4 + 1] << 16) | ((uint32_t)d[offset + i * 4 + 2] << 8) | (uint32_t)d[offset + i * 4 + 3];
}
for (i = 16; i < 80; i++) {
uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
w[i] = (x << 1) | (x >> 31);
}
a = h0;
b = h1;
c = h2;
e = h3;
f = h4;
for (i = 0; i < 80; i++) {
uint32_t fmix;
if (i < 20) {
fmix = (b & c) | ((~b) & e);
k = 0x5A827999u;
} else if (i < 40) {
fmix = b ^ c ^ e;
k = 0x6ED9EBA1u;
} else if (i < 60) {
fmix = (b & c) | (b & e) | (c & e);
k = 0x8F1BBCDCu;
} else {
fmix = b ^ c ^ e;
k = 0xCA62C1D6u;
}
temp = ((a << 5) | (a >> 27)) + fmix + f + k + w[i];
f = e;
e = c;
c = (b << 30) | (b >> 2);
b = a;
a = temp;
}
h0 += a;
h1 += b;
h2 += c;
h3 += e;
h4 += f;
offset += 64;
}
total = n - offset;
memset(block, 0, sizeof(block));
if (total) {
memcpy(block, d + offset, total);
}
block[total] = 0x80;
if (total >= 56) {
uint32_t w[80];
uint32_t a, b, c, e, f, temp;
for (i = 0; i < 16; i++) {
w[i] = ((uint32_t)block[i * 4] << 24) | ((uint32_t)block[i * 4 + 1] << 16) | ((uint32_t)block[i * 4 + 2] << 8) | (uint32_t)block[i * 4 + 3];
}
for (i = 16; i < 80; i++) {
uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
w[i] = (x << 1) | (x >> 31);
}
a = h0;
b = h1;
c = h2;
e = h3;
f = h4;
for (i = 0; i < 80; i++) {
uint32_t fmix;
uint32_t k;
if (i < 20) {
fmix = (b & c) | ((~b) & e);
k = 0x5A827999u;
} else if (i < 40) {
fmix = b ^ c ^ e;
k = 0x6ED9EBA1u;
} else if (i < 60) {
fmix = (b & c) | (b & e) | (c & e);
k = 0x8F1BBCDCu;
} else {
fmix = b ^ c ^ e;
k = 0xCA62C1D6u;
}
temp = ((a << 5) | (a >> 27)) + fmix + f + k + w[i];
f = e;
e = c;
c = (b << 30) | (b >> 2);
b = a;
a = temp;
}
h0 += a;
h1 += b;
h2 += c;
h3 += e;
h4 += f;
memset(block, 0, sizeof(block));
}
block[56] = (unsigned char)((bit_len_hi >> 24) & 0xFF);
block[57] = (unsigned char)((bit_len_hi >> 16) & 0xFF);
block[58] = (unsigned char)((bit_len_hi >> 8) & 0xFF);
block[59] = (unsigned char)(bit_len_hi & 0xFF);
block[60] = (unsigned char)((bit_len_lo >> 24) & 0xFF);
block[61] = (unsigned char)((bit_len_lo >> 16) & 0xFF);
block[62] = (unsigned char)((bit_len_lo >> 8) & 0xFF);
block[63] = (unsigned char)(bit_len_lo & 0xFF);
{
uint32_t w[80];
uint32_t a, b, c, e, f, temp;
for (i = 0; i < 16; i++) {
w[i] = ((uint32_t)block[i * 4] << 24) | ((uint32_t)block[i * 4 + 1] << 16) | ((uint32_t)block[i * 4 + 2] << 8) | (uint32_t)block[i * 4 + 3];
}
for (i = 16; i < 80; i++) {
uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
w[i] = (x << 1) | (x >> 31);
}
a = h0;
b = h1;
c = h2;
e = h3;
f = h4;
for (i = 0; i < 80; i++) {
uint32_t fmix;
uint32_t k;
if (i < 20) {
fmix = (b & c) | ((~b) & e);
k = 0x5A827999u;
} else if (i < 40) {
fmix = b ^ c ^ e;
k = 0x6ED9EBA1u;
} else if (i < 60) {
fmix = (b & c) | (b & e) | (c & e);
k = 0x8F1BBCDCu;
} else {
fmix = b ^ c ^ e;
k = 0xCA62C1D6u;
}
temp = ((a << 5) | (a >> 27)) + fmix + f + k + w[i];
f = e;
e = c;
c = (b << 30) | (b >> 2);
b = a;
a = temp;
}
h0 += a;
h1 += b;
h2 += c;
h3 += e;
h4 += f;
}
md[0] = (unsigned char)(h0 >> 24);
md[1] = (unsigned char)(h0 >> 16);
md[2] = (unsigned char)(h0 >> 8);
md[3] = (unsigned char)h0;
md[4] = (unsigned char)(h1 >> 24);
md[5] = (unsigned char)(h1 >> 16);
md[6] = (unsigned char)(h1 >> 8);
md[7] = (unsigned char)h1;
md[8] = (unsigned char)(h2 >> 24);
md[9] = (unsigned char)(h2 >> 16);
md[10] = (unsigned char)(h2 >> 8);
md[11] = (unsigned char)h2;
md[12] = (unsigned char)(h3 >> 24);
md[13] = (unsigned char)(h3 >> 16);
md[14] = (unsigned char)(h3 >> 8);
md[15] = (unsigned char)h3;
md[16] = (unsigned char)(h4 >> 24);
md[17] = (unsigned char)(h4 >> 16);
md[18] = (unsigned char)(h4 >> 8);
md[19] = (unsigned char)h4;
return md;
}
+85
View File
@@ -0,0 +1,85 @@
/* This file is a part of the UMSKT Project.
*
* Copyleft (C) 2019-2026 UMSKT Contributors (et.al.)
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#ifndef UMSKT_MINI_OPENSSL_H
#define UMSKT_MINI_OPENSSL_H
#include <stddef.h>
#include <stdint.h>
#define BN_RAND_TOP_ANY (-1)
#define BN_RAND_TOP_ONE 0
#define BN_RAND_TOP_TWO 1
#define BN_RAND_BOTTOM_ANY 0
#define BN_RAND_BOTTOM_ODD 1
#define SHA_DIGEST_LENGTH 20
typedef uint32_t BN_ULONG;
struct bignum_st;
struct bn_ctx_st;
struct ec_group_st;
struct ec_point_st;
typedef struct bignum_st BIGNUM;
typedef struct bn_ctx_st BN_CTX;
typedef struct ec_group_st EC_GROUP;
typedef struct ec_point_st EC_POINT;
BIGNUM *BN_new(void);
BIGNUM *BN_dup(const BIGNUM *a);
void BN_free(BIGNUM *a);
int BN_zero(BIGNUM *a);
int BN_set_word(BIGNUM *a, BN_ULONG w);
int BN_copy(BIGNUM *to, const BIGNUM *from);
int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
int BN_is_zero(const BIGNUM *a);
int BN_is_odd(const BIGNUM *a);
int BN_num_bits(const BIGNUM *a);
int BN_num_bytes(const BIGNUM *a);
int BN_set_bit(BIGNUM *a, int n);
int BN_is_bit_set(const BIGNUM *a, int n);
int BN_mask_bits(BIGNUM *a, int n);
int BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
int BN_rshift1(BIGNUM *r, const BIGNUM *a);
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
int BN_mul_word(BIGNUM *a, BN_ULONG w);
int BN_add_word(BIGNUM *a, BN_ULONG w);
int BN_sub_word(BIGNUM *a, BN_ULONG w);
BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
int BN_dec2bn(BIGNUM **a, const char *str);
char *BN_bn2dec(const BIGNUM *a);
int BN_bn2bin(const BIGNUM *a, unsigned char *to);
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen);
int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_inverse(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
BIGNUM *BN_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
BN_CTX *BN_CTX_new(void);
void BN_CTX_free(BN_CTX *ctx);
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
void EC_GROUP_free(EC_GROUP *group);
EC_POINT *EC_POINT_new(const EC_GROUP *group);
void EC_POINT_free(EC_POINT *point);
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx);
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md);
int RAND_bytes(unsigned char *buf, int num);
#endif
+183
View File
@@ -0,0 +1,183 @@
/* This file is a part of the UMSKT Project.
*
* Copyleft (C) 2019-2026 UMSKT Contributors (et.al.)
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include "mini_openssl.h"
#include <stdint.h>
#include <string.h>
#if defined(_WIN32)
#ifndef WINVER
#define WINVER 0x0400
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#ifndef NTDDI_VERSION
#define NTDDI_VERSION 0x04000000
#endif
#include <windows.h>
#elif defined(__DJGPP__)
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
extern "C" long int random(void);
extern "C" int srandom(int seed);
#else
#include <stdio.h>
#include <time.h>
#endif
static uint32_t rng_state[4] = {0xA3C59AC3u, 0x6F372C1Du, 0x19E8B2A5u, 0xC0FFEE11u};
static int rng_ready = 0;
static uint32_t rng_step(void) {
uint32_t t = rng_state[3];
uint32_t s = rng_state[0];
rng_state[3] = rng_state[2];
rng_state[2] = rng_state[1];
rng_state[1] = s;
t ^= t << 11;
t ^= t >> 8;
rng_state[0] = t ^ s ^ (s >> 19);
return rng_state[0];
}
static void rng_mix(uint32_t extra) {
rng_state[0] ^= extra;
rng_state[1] ^= extra * 0x9E3779B9u;
rng_step();
rng_step();
}
static void rng_fill(unsigned char *buf, int num) {
int filled = 0;
int i;
for (i = 0; i < num; i++) {
if ((i & 3) == 0) {
filled = (int)rng_step();
}
buf[i] = (unsigned char)(filled & 0xFF);
filled >>= 8;
}
}
#if defined(_WIN32)
typedef int (WINAPI *CryptAcquireContextA_fn)(uintptr_t *prov, const char *container, const char *provider, unsigned long type, unsigned long flags);
typedef int (WINAPI *CryptGenRandom_fn)(uintptr_t prov, unsigned long len, unsigned char *buf);
typedef int (WINAPI *CryptReleaseContext_fn)(uintptr_t prov, unsigned long flags);
static void rng_stir(void) {
LARGE_INTEGER counter;
SYSTEMTIME time;
counter.QuadPart = 0;
QueryPerformanceCounter(&counter);
GetSystemTime(&time);
rng_mix(GetTickCount());
rng_mix((uint32_t)counter.LowPart);
rng_mix((uint32_t)counter.HighPart);
rng_mix(((uint32_t)time.wMilliseconds << 16) ^ ((uint32_t)time.wSecond << 8) ^ time.wMinute);
rng_mix(GetCurrentProcessId() ^ ((uint32_t)GetCurrentThreadId() << 16));
}
static int rng_capi(unsigned char *buf, int num) {
HMODULE advapi;
CryptAcquireContextA_fn acquire;
CryptGenRandom_fn generate;
CryptReleaseContext_fn release;
uintptr_t prov = 0;
int ok;
advapi = LoadLibraryA("advapi32.dll");
if (!advapi) {
return 0;
}
acquire = (CryptAcquireContextA_fn)GetProcAddress(advapi, "CryptAcquireContextA");
generate = (CryptGenRandom_fn)GetProcAddress(advapi, "CryptGenRandom");
release = (CryptReleaseContext_fn)GetProcAddress(advapi, "CryptReleaseContext");
if (!acquire || !generate || !release) {
FreeLibrary(advapi);
return 0;
}
if (!acquire(&prov, NULL, NULL, 1, 0xF0000000u)) {
FreeLibrary(advapi);
return 0;
}
ok = generate(prov, (unsigned long)num, buf);
release(prov, 0);
FreeLibrary(advapi);
return ok ? 1 : 0;
}
int RAND_bytes(unsigned char *buf, int num) {
unsigned char extra[256];
int i;
if (!buf || num < 0) {
return 0;
}
if (!rng_ready) {
rng_stir();
rng_ready = 1;
}
rng_stir();
if (num <= (int)sizeof(extra) && rng_capi(extra, num)) {
for (i = 0; i < num; i++) {
buf[i] = (unsigned char)(extra[i] ^ (rng_step() & 0xFF));
}
return 1;
}
rng_fill(buf, num);
return 1;
}
#elif defined(__DJGPP__)
int RAND_bytes(unsigned char *buf, int num) {
int i;
if (!buf || num < 0) {
return 0;
}
if (!rng_ready) {
struct timeval tv;
int seed;
gettimeofday(&tv, NULL);
seed = (int)(tv.tv_sec ^ tv.tv_usec);
srandom(seed);
srand(seed ^ 0x1234ABCD);
rng_mix((uint32_t)seed);
rng_ready = 1;
}
for (i = 0; i < num; i++) {
buf[i] = (unsigned char)((random() ^ rand()) & 0xFF);
}
return 1;
}
#else
static void rng_stir(void) {
rng_mix((uint32_t)time(NULL));
rng_mix((uint32_t)clock());
}
int RAND_bytes(unsigned char *buf, int num) {
FILE *random_file;
size_t got = 0;
if (!buf || num < 0) {
return 0;
}
random_file = fopen("/dev/urandom", "rb");
if (random_file) {
got = fread(buf, 1, (size_t)num, random_file);
fclose(random_file);
if (got == (size_t)num) {
return 1;
}
}
if (!rng_ready) {
rng_stir();
rng_ready = 1;
}
rng_stir();
rng_fill(buf, num);
return 1;
}
#endif
-41
View File
@@ -1,41 +0,0 @@
/**
* This file is a part of the UMSKT Project
*
* Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 5/26/2023
* @Maintainer Neo
*/
#ifndef UMSKT_HEADER_H
#define UMSKT_HEADER_H
#include "typedefs.h"
#include <iostream>
#include <fstream>
#include <filesystem>
#include <string>
#include <vector>
#include <unordered_map>
#include <fmt/core.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace fs = std::filesystem;
#endif //UMSKT_HEADER_H
+8
View File
@@ -0,0 +1,8 @@
#ifndef UMSKT_KEYS_EMBED_H
#define UMSKT_KEYS_EMBED_H
/* Generated from keys.json. The bytes are not NUL-terminated; use the size. */
extern const char umskt_keys_json[];
extern const int umskt_keys_json_size;
#endif
+56 -16
View File
@@ -789,7 +789,48 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
}
}
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid, bool overrideVersion)
static int dec_at(const char *text, int offset, int count) {
int value = 0;
int index;
if (!text) {
return 0;
}
for (index = 0; index < offset; index++) {
if (!text[index]) {
return 0;
}
}
for (index = 0; index < count; index++) {
char ch = text[offset + index];
if (ch < '0' || ch > '9') {
break;
}
value = value * 10 + (ch - '0');
}
return value;
}
static void take_upper(char *dst, const char *text, int offset, int count) {
int index = 0;
int seen = 0;
if (text) {
while (text[seen] && seen < offset) {
seen++;
}
if (seen == offset) {
for (; index < count && text[offset + index]; index++) {
char ch = text[offset + index];
if (ch >= 'a' && ch <= 'z') {
ch = (char)(ch - 32);
}
dst[index] = ch;
}
}
}
dst[index] = 0;
}
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], int mode, const char *productid, bool overrideVersion)
{
int version;
unsigned char hardwareID[8];
@@ -951,21 +992,20 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
}
}
memcpy(&parsed, hardwareID, 8);
productID[0] = 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) {
productID[1] = stoi(productid.substr(12,3));
productID[2] = (stoi(productid.substr(15,1)) * 100000) + stoi(productid.substr(18,5));
productID[2] = calculateCheckDigit(productID[2]);
productID[3] = ((stoi(productid.substr(10,2))) * 1000) + productID[3];
} else {
productID[1] = stoi(productid.substr(6,3));
productID[2] = stoi(productid.substr(10,7));
productID[3] = stoi(productid.substr(18,5));
{
char channelid[8];
productID[0] = dec_at(productid, 0, 5);
take_upper(channelid, productid, 6, 3);
if (strcmp(channelid, "OEM") == 0) {
productID[1] = dec_at(productid, 12, 3);
productID[2] = (dec_at(productid, 15, 1) * 100000) + dec_at(productid, 18, 5);
productID[2] = calculateCheckDigit(productID[2]);
productID[3] = (dec_at(productid, 10, 2) * 1000) + productID[3];
} else {
productID[1] = dec_at(productid, 6, 3);
productID[2] = dec_at(productid, 10, 7);
productID[3] = dec_at(productid, 18, 5);
}
}
}
// fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
+1 -1
View File
@@ -66,7 +66,7 @@ EXPORT class ConfirmationID {
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], int mode, std::string productid, bool overrideVersion);
static int Generate(const char* installation_id_str, char confirmation_id[49], int mode, const char *productid, bool overrideVersion);
//EXPORT static int CLIRun();
};
+40 -7
View File
@@ -7,7 +7,7 @@
* 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
@@ -22,14 +22,47 @@
#include "libumskt.h"
#ifdef UMSKT_FREESTANDING
#include "../windows/win32_min.h"
#ifdef _WIN32
std::FILE* UMSKT::debug = std::fopen("NUL:", "w");
int UMSKT::debug_on = 0;
void UMSKT::setDebug(int on) {
debug_on = on;
}
void UMSKT::debugf(const char *fmt, ...) {
char buffer[1024];
va_list ap;
uint32_t wrote = 0;
if (!debug_on || !fmt) {
return;
}
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
WriteFile(GetStdHandle(UMSKT_STD_ERROR_HANDLE), buffer, (uint32_t)strlen(buffer), &wrote, 0);
}
#else
std::FILE* UMSKT::debug = std::fopen("/dev/null", "w");
#ifdef _WIN32
FILE *UMSKT::debug = fopen("NUL:", "w");
#else
FILE *UMSKT::debug = fopen("/dev/null", "w");
#endif
void UMSKT::setDebugOutput(std::FILE* input) {
debug = input;
void UMSKT::setDebug(int on) {
if (on) {
debug = stderr;
}
}
void UMSKT::debugf(const char *fmt, ...) {
va_list ap;
if (!debug || !fmt) {
return;
}
va_start(ap, fmt);
vfprintf(debug, fmt, ap);
va_end(ap);
}
#endif
+5 -72
View File
@@ -27,7 +27,7 @@
#include "pidgen3/BINK2002.h"
#include "pidgen2/PIDGEN2.h"
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid, bool bypassVersion) {
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, const char *productid, bool bypassVersion) {
return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid, bypassVersion);
}
@@ -35,19 +35,19 @@ FNEXPORT EC_GROUP* PIDGEN3_initializeEllipticCurve(char* pSel, char* aSel, char*
return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel, publicKeyYSel, genPoint, pubPoint);
}
FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25]) {
FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[PK_LENGTH + NULL_TERMINATOR]) {
return PIDGEN3::BINK1998::Verify(eCurve, basePoint, publicKey, pKey);
}
FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, BOOL pUpgrade,char (&pKey)[25]) {
FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, BOOL pUpgrade,char (&pKey)[PK_LENGTH + NULL_TERMINATOR]) {
return PIDGEN3::BINK1998::Generate(eCurve, basePoint, genOrder, privateKey, pSerial, pUpgrade, pKey);
}
FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, DWORD *pSerial, char (&cdKey)[25]) {
FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, DWORD *pSerial, char (&cdKey)[PK_LENGTH + NULL_TERMINATOR]) {
return PIDGEN3::BINK2002::Verify(eCurve, basePoint, publicKey, pSerial, cdKey);
}
FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, DWORD serMin, DWORD serMax, char (&pKey)[25]) {
FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, DWORD serMin, DWORD serMax, char (&pKey)[PK_LENGTH + NULL_TERMINATOR]) {
return PIDGEN3::BINK2002::Generate(eCurve, basePoint, genOrder, privateKey, pChannelID, pAuthInfo, pUpgrade, serMin, serMax, pKey);
}
@@ -59,77 +59,10 @@ FNEXPORT int PIDGEN2_GenerateOEM(char* year, char* day, char* oem, char* keyout)
return PIDGEN2::GenerateOEM(year, day, oem, keyout);
}
// RNG utility functions
int UMSKT::umskt_rand_bytes(unsigned char *buf, int num) {
#if UMSKT_RNG_DJGPP
// DOS-compatible RNG using DJGPP's random() function
static bool initialized = false;
if (!initialized) {
// Get initial seed from multiple sources for better entropy
struct timeval tv;
gettimeofday(&tv, NULL);
// Combine microseconds with BIOS timer ticks
unsigned long ticks = *(volatile unsigned long *)0x0040001CL;
int seed = (int)((tv.tv_sec ^ tv.tv_usec) ^ (ticks * 100000));
// Initialize both random() and rand() with different seeds
srandom(seed);
srand(seed ^ 0x1234ABCD); // Use a different seed for rand
initialized = true;
}
for (int i = 0; i < num; i++) {
// Use random() for better randomness, especially in lower bits
buf[i] = (unsigned char)(random() & 0xFF);
// Mix in rand() as an additional source
buf[i] ^= (unsigned char)(rand() & 0xFF);
}
return 1;
#else
// Use OpenSSL's RAND_bytes for non-DOS systems
return RAND_bytes(buf, num);
#endif
}
int UMSKT::umskt_bn_rand(BIGNUM *rnd, int bits, int top, int bottom) {
#if UMSKT_RNG_DJGPP
// DOS-compatible RNG implementation for BIGNUMs
unsigned char *buf = (unsigned char *)malloc((bits + 7) / 8);
if (!buf) return 0;
// Generate random bytes
umskt_rand_bytes(buf, (bits + 7) / 8);
// Convert to BIGNUM
if (!BN_bin2bn(buf, (bits + 7) / 8, rnd)) {
free(buf);
return 0;
}
free(buf);
// Apply top/bottom constraints like BN_rand does
if (top != -1) {
if (top) {
if (bits == 0) {
BN_zero(rnd);
return 1;
}
BN_set_bit(rnd, bits - 1);
}
BN_mask_bits(rnd, bits);
}
if (bottom) {
BN_set_bit(rnd, 0);
}
return 1;
#else
// Use OpenSSL's BN_rand for non-DOS systems
return BN_rand(rnd, bits, top, bottom);
#endif
}
+11 -28
View File
@@ -25,22 +25,11 @@
#include "../typedefs.h"
#include <string>
#include <iostream>
#include <sstream>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <fmt/core.h>
#include <fmt/format.h>
#ifdef __DJGPP__
#include <sys/time.h>
#endif
#include "../crypto/mini_openssl.h"
// Algorithm macros
#define PK_LENGTH 25
@@ -63,25 +52,19 @@
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1)
// RNG utility functions
#ifdef __DJGPP__
#define UMSKT_RNG_DJGPP 1
extern "C" {
long int random(void);
int srandom(int seed);
}
#else
#define UMSKT_RNG_DJGPP 0
#endif
class UMSKT {
public:
static std::FILE* debug;
class PIDGEN2;
class PIDGEN3;
class ConfigurationID;
static void setDebugOutput(std::FILE* input);
#ifdef UMSKT_FREESTANDING
static int debug_on;
#else
static FILE *debug;
#endif
static void setDebug(int on);
static void debugf(const char *fmt, ...);
// RNG utility functions
static int umskt_rand_bytes(unsigned char *buf, int num);
+23 -4
View File
@@ -22,6 +22,18 @@
#include "PIDGEN2.h"
static int parse_i(const char *text) {
int value = 0;
if (!text) {
return 0;
}
while (*text >= '0' && *text <= '9') {
value = value * 10 + (*text - '0');
text++;
}
return value;
}
const char* channelIDBlacklist [7] = {"333", "444", "555", "666", "777", "888", "999"};
const char* validYears[8] = { "95", "96", "97", "98", "99", "00", "01", "02"};
@@ -93,7 +105,7 @@ bool PIDGEN2::isValidDay(char* day) {
return false;
}
int iDay = std::stoi(day);
int iDay = parse_i(day);
if (iDay == 0 || iDay >= 365) {
return false;
}
@@ -117,7 +129,9 @@ int PIDGEN2::GenerateOEM(char* year, char* day, char* oem, char* &keyout) {
int mod = addDigits(oem);
mod += mod % 21;
strcpy(oem, fmt::format("{:07d}", mod).c_str());
char formatted[16];
snprintf(formatted, sizeof(formatted), "%07d", mod);
strcpy(oem, formatted);
}
if (!isValidYear(year)) {
@@ -125,11 +139,16 @@ int PIDGEN2::GenerateOEM(char* year, char* day, char* oem, char* &keyout) {
}
if (!isValidDay(day)) {
int iday = std::stoi(day);
int iday = parse_i(day);
iday = (iday + 1) % 365;
(void)iday;
}
strcpy(keyout, fmt::format("{}{}-OEM-{}-{}", year, day, oem, oem).c_str());
{
char formatted[64];
snprintf(formatted, sizeof(formatted), "%s%s-OEM-%s-%s", year, day, oem, oem);
strcpy(keyout, formatted);
}
return 0;
}
+35 -28
View File
@@ -75,7 +75,7 @@ bool PIDGEN3::BINK1998::Verify(
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&pKey)[25]
char (&pKey)[PK_LENGTH + NULL_TERMINATOR]
) {
BN_CTX *numContext = BN_CTX_new();
@@ -94,12 +94,12 @@ bool PIDGEN3::BINK1998::Verify(
// Extract RPK, hash and signature from bytecode.
Unpack(pRaw, pUpgrade, pSerial, pHash, pSignature);
fmt::print(UMSKT::debug, "Validation results:\n");
fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
fmt::print(UMSKT::debug, " Serial: 0x{:08x}\n", pSerial);
fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
fmt::print(UMSKT::debug, "\n");
UMSKT::debugf("Validation results:\n");
UMSKT::debugf(" Upgrade: 0x%08x\n", (unsigned)pUpgrade);
UMSKT::debugf(" Serial: 0x%08x\n", (unsigned)pSerial);
UMSKT::debugf(" Hash: 0x%08x\n", (unsigned)pHash);
UMSKT::debugf(" Signature: 0x%08llx\n", (unsigned long long)pSignature);
UMSKT::debugf("\n");
pData = pSerial << 1 | pUpgrade;
@@ -182,7 +182,7 @@ void PIDGEN3::BINK1998::Generate(
BIGNUM *privateKey,
DWORD pSerial,
BOOL pUpgrade,
char (&pKey)[25]
char (&pKey)[PK_LENGTH + NULL_TERMINATOR]
) {
BN_CTX *numContext = BN_CTX_new();
@@ -196,18 +196,16 @@ void PIDGEN3::BINK1998::Generate(
// Data segment of the RPK.
DWORD pData = pSerial << 1 | pUpgrade;
int tries = 0;
// One random scalar. Further candidates are c+1, c+2, ... so each extra
// attempt adds G instead of multiplying the curve again. About 1 in 512
// signatures fit in 55 bits, and a 386 cannot afford hundreds of multiplications.
EC_POINT *r = EC_POINT_new(eCurve);
UMSKT::umskt_bn_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);
do {
EC_POINT *r = EC_POINT_new(eCurve);
// Generate a random number c consisting of 384 bits without any constraints.
UMSKT::umskt_bn_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
// Pick a random derivative of the base point on the elliptic curve.
// R = cG;
EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);
// Acquire its coordinates.
// x = R.x; y = R.y;
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
@@ -258,25 +256,34 @@ void PIDGEN3::BINK1998::Generate(
// s += c (mod n)
BN_mod_add(s, s, c, genOrder, numContext);
// Translate resulting scalar into a 64-bit integer (the byte order is little-endian).
BN_bn2lebinpad(s, (BYTE *)&pSignature, BN_num_bytes(s));
// Low 64 bits only. The scalar is wider than this field, and the
// destination is an 8-byte QWORD.
BN_mask_bits(s, 64);
pSignature = 0;
BN_bn2lebinpad(s, (BYTE *)&pSignature, (int)sizeof(pSignature));
tries++;
// Pack product key.
Pack(pRaw, pUpgrade, pSerial, pHash, pSignature);
fmt::print(UMSKT::debug, "Generation results:\n");
fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
fmt::print(UMSKT::debug, " Serial: 0x{:08x}\n", pSerial);
fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
fmt::print(UMSKT::debug, "\n");
UMSKT::debugf("Generation results:\n");
UMSKT::debugf(" Upgrade: 0x%08x\n", (unsigned)pUpgrade);
UMSKT::debugf(" Serial: 0x%08x\n", (unsigned)pSerial);
UMSKT::debugf(" Hash: 0x%08x\n", (unsigned)pHash);
UMSKT::debugf(" Signature: 0x%08llx\n", (unsigned long long)pSignature);
UMSKT::debugf("\n");
EC_POINT_free(r);
} while (pSignature > BITMASK(55));
if (tries < 4096 && pSignature > BITMASK(55)) {
EC_POINT_add(eCurve, r, r, basePoint, numContext);
BN_add_word(c, 1);
}
} while (tries < 4096 && pSignature > BITMASK(55));
// ↑ ↑ ↑
// The signature can't be longer than 55 bits, else it will
// make the CD-key longer than 25 characters.
EC_POINT_free(r);
// Convert bytecode to Base24 CD-key.
base24(pKey, (BYTE *)pRaw);
+2 -2
View File
@@ -47,7 +47,7 @@ public:
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&pKey)[25]
char (&pKey)[PK_LENGTH + NULL_TERMINATOR]
);
static void Generate(
@@ -57,7 +57,7 @@ public:
BIGNUM *privateKey,
DWORD pSerial,
BOOL pUpgrade,
char (&pKey)[25]
char (&pKey)[PK_LENGTH + NULL_TERMINATOR]
);
};
+56 -38
View File
@@ -79,7 +79,7 @@ bool PIDGEN3::BINK2002::Verify(
EC_POINT *basePoint,
EC_POINT *publicKey,
DWORD *pSerial,
char (&cdKey)[25]
char (&cdKey)[PK_LENGTH + NULL_TERMINATOR]
) {
BN_CTX *context = BN_CTX_new();
@@ -183,14 +183,14 @@ bool PIDGEN3::BINK2002::Verify(
DWORD serial = (((BYDWORD(msgDigest + 4) >> 13) << 1) | (BYDWORD(msgDigest) >> 31)) & BITMASK(20);
if (pSerial != nullptr) *pSerial = serial;
fmt::print(UMSKT::debug, "Validation results:\n");
fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", pChannelID);
fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo);
fmt::print(UMSKT::debug, " Serial: {:06d}\n", serial);
fmt::print(UMSKT::debug, "\n");
UMSKT::debugf("Validation results:\n");
UMSKT::debugf(" Upgrade: 0x%08x\n", (unsigned)pUpgrade);
UMSKT::debugf("Channel ID: 0x%08x\n", (unsigned)pChannelID);
UMSKT::debugf(" Hash: 0x%08x\n", (unsigned)pHash);
UMSKT::debugf(" Signature: 0x%08llx\n", (unsigned long long)pSignature);
UMSKT::debugf(" AuthInfo: 0x%08x\n", (unsigned)pAuthInfo);
UMSKT::debugf(" Serial: %06u\n", (unsigned)serial);
UMSKT::debugf("\n");
// Translate the byte digest into a 32-bit integer - this is our computed hash.
// Truncate the hash to 31 bits.
@@ -221,11 +221,12 @@ void PIDGEN3::BINK2002::Generate(
BOOL pUpgrade,
DWORD serMin,
DWORD serMax,
char (&pKey)[25]
char (&pKey)[PK_LENGTH + NULL_TERMINATOR]
) {
BN_CTX *numContext = BN_CTX_new();
BIGNUM *c = BN_new(),
*c4 = BN_new(),
*e = BN_new(),
*s = BN_new(),
*x = BN_new(),
@@ -233,23 +234,21 @@ void PIDGEN3::BINK2002::Generate(
QWORD pRaw[2]{},
pSignature = 0;
int tries = 0;
// Data segment of the RPK.
DWORD pData = pChannelID << 1 | pUpgrade;
BOOL noSquare;
BOOL serialInRange;
BOOL noSquare = true;
BOOL serialInRange = false;
// One random scalar. Further candidates are c+1, c+2, ... so each extra
// attempt adds G instead of multiplying the curve again.
EC_POINT *r = EC_POINT_new(eCurve);
UMSKT::umskt_bn_rand(c, FIELD_BITS_2003, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);
do {
EC_POINT *r = EC_POINT_new(eCurve);
// Generate a random number c consisting of 512 bits without any constraints.
UMSKT::umskt_bn_rand(c, FIELD_BITS_2003, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
// R = cG
EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);
// Acquire its coordinates.
// x = R.x; y = R.y;
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
@@ -278,7 +277,15 @@ void PIDGEN3::BINK2002::Generate(
DWORD serial = (((BYDWORD(msgDigest + 4) >> 13) << 1) | (BYDWORD(msgDigest) >> 31)) & BITMASK(20);
serialInRange = (serial >= serMin) && (serial <= serMax);
if (!serialInRange) continue;
if (!serialInRange) {
noSquare = true;
tries++;
if (tries < 4096) {
EC_POINT_add(eCurve, r, r, basePoint, numContext);
BN_add_word(c, 1);
}
continue;
}
// Translate the byte digest into a 32-bit integer - this is our computed hash.
// Truncate the hash to 31 bits.
@@ -345,11 +352,12 @@ void PIDGEN3::BINK2002::Generate(
// s = (ek (mod n))²
BN_mod_sqr(s, s, genOrder, numContext);
// c *= 4 (c <<= 2)
BN_lshift(c, c, 2);
// 4c is a copy. c itself stays the scalar of R for the next step.
BN_copy(c4, c);
BN_lshift(c4, c4, 2);
// s += c
BN_add(s, s, c);
// s += 4c
BN_add(s, s, c4);
// Around half of numbers modulo a prime are not squares -> BN_sqrt_mod fails about half of the times,
// hence if BN_sqrt_mod returns NULL, we need to restart with a different seed.
@@ -369,31 +377,41 @@ void PIDGEN3::BINK2002::Generate(
// s /= 2 (s >>= 1)
BN_rshift1(s, s);
// Translate resulting scalar into a 64-bit integer (the byte order is little-endian).
BN_bn2lebinpad(s, (BYTE *)&pSignature, BN_num_bytes(s));
// Low 64 bits only. The scalar is wider than this field, and the
// destination is an 8-byte QWORD.
BN_mask_bits(s, 64);
pSignature = 0;
BN_bn2lebinpad(s, (BYTE *)&pSignature, (int)sizeof(pSignature));
tries++;
// Pack product key.
Pack(pRaw, pUpgrade, pChannelID, pHash, pSignature, pAuthInfo);
fmt::print(UMSKT::debug, "Generation results:\n");
fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade);
fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", pChannelID);
fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash);
fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature);
fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo);
fmt::print(UMSKT::debug, " Serial: {:06d}\n", serial);
fmt::print(UMSKT::debug, "\n");
UMSKT::debugf("Generation results:\n");
UMSKT::debugf(" Upgrade: 0x%08x\n", (unsigned)pUpgrade);
UMSKT::debugf("Channel ID: 0x%08x\n", (unsigned)pChannelID);
UMSKT::debugf(" Hash: 0x%08x\n", (unsigned)pHash);
UMSKT::debugf(" Signature: 0x%08llx\n", (unsigned long long)pSignature);
UMSKT::debugf(" AuthInfo: 0x%08x\n", (unsigned)pAuthInfo);
UMSKT::debugf(" Serial: %06u\n", (unsigned)serial);
UMSKT::debugf("\n");
EC_POINT_free(r);
} while (pSignature > BITMASK(62) || noSquare || !serialInRange);
if (tries < 4096 && (pSignature > BITMASK(62) || noSquare || !serialInRange)) {
EC_POINT_add(eCurve, r, r, basePoint, numContext);
BN_add_word(c, 1);
}
} while (tries < 4096 && (pSignature > BITMASK(62) || noSquare || !serialInRange));
// ↑ ↑ ↑
// The signature can't be longer than 62 bits, else it will
// overlap with the AuthInfo segment next to it.
EC_POINT_free(r);
// Convert bytecode to Base24 CD-key.
base24(pKey, (BYTE *)pRaw);
BN_free(c);
BN_free(c4);
BN_free(s);
BN_free(x);
BN_free(y);
+2 -2
View File
@@ -50,7 +50,7 @@ public:
EC_POINT *basePoint,
EC_POINT *publicKey,
DWORD *pSerial,
char (&cdKey)[25]
char (&cdKey)[PK_LENGTH + NULL_TERMINATOR]
);
static void Generate(
@@ -63,7 +63,7 @@ public:
BOOL pUpgrade,
DWORD serMin,
DWORD serMax,
char (&pKey)[25]
char (&pKey)[PK_LENGTH + NULL_TERMINATOR]
);
};
+7 -7
View File
@@ -34,13 +34,13 @@ public:
static int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); // Hello OpenSSL developers, please tell me, where is this function at?
static void endian(BYTE *data, int length);
static EC_GROUP* initializeEllipticCurve(
std::string pSel,
std::string aSel,
std::string bSel,
std::string generatorXSel,
std::string generatorYSel,
std::string publicKeyXSel,
std::string publicKeyYSel,
const char *pSel,
const char *aSel,
const char *bSel,
const char *generatorXSel,
const char *generatorYSel,
const char *publicKeyXSel,
const char *publicKeyYSel,
EC_POINT *&genPoint,
EC_POINT *&pubPoint
);
+2 -2
View File
@@ -76,8 +76,8 @@ void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
// Convert reversed byte sequence to BigNum z.
z = BN_bin2bn(rbyteSeq, length, nullptr);
// Divide z by 24 and convert the remainder to a CD-key char.
cdKey[25] = 0;
// 25 key characters plus the terminator. Callers pass PK_LENGTH + NULL_TERMINATOR.
cdKey[PK_LENGTH] = 0;
for (int i = 24; i >= 0; i--)
cdKey[i] = pKeyCharset[BN_div_word(z, 24)];
+14 -14
View File
@@ -38,13 +38,13 @@ void PIDGEN3::endian(BYTE *data, int length) {
/* Initializes the elliptic curve. */
EC_GROUP* PIDGEN3::initializeEllipticCurve(
const std::string pSel,
const std::string aSel,
const std::string bSel,
const std::string generatorXSel,
const std::string generatorYSel,
const std::string publicKeyXSel,
const std::string publicKeyYSel,
const char *pSel,
const char *aSel,
const char *bSel,
const char *generatorXSel,
const char *generatorYSel,
const char *publicKeyXSel,
const char *publicKeyYSel,
EC_POINT *&genPoint,
EC_POINT *&pubPoint
) {
@@ -72,14 +72,14 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
context = BN_CTX_new();
/* Public data */
BN_dec2bn(&p, pSel.c_str());
BN_dec2bn(&a, aSel.c_str());
BN_dec2bn(&b, bSel.c_str());
BN_dec2bn(&generatorX, generatorXSel.c_str());
BN_dec2bn(&generatorY, generatorYSel.c_str());
BN_dec2bn(&p, pSel);
BN_dec2bn(&a, aSel);
BN_dec2bn(&b, bSel);
BN_dec2bn(&generatorX, generatorXSel);
BN_dec2bn(&generatorY, generatorYSel);
BN_dec2bn(&publicKeyX, publicKeyXSel.c_str());
BN_dec2bn(&publicKeyY, publicKeyYSel.c_str());
BN_dec2bn(&publicKeyX, publicKeyXSel);
BN_dec2bn(&publicKeyY, publicKeyYSel);
/* Elliptic Curve calculations. */
// The group is defined via Fp = all integers [0; p - 1], where p is prime.
-63
View File
@@ -1,63 +0,0 @@
/**
* This file is a part of the UMSKT Project
*
* Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Andrew on 01/06/2023
* @Maintainer Neo
*/
#include "header.h"
#include "cli.h"
Options options;
int main(int argc, char *argv[]) {
if (!CLI::parseCommandLine(argc, argv, &options)) {
fmt::print("error parsing command line options\n");
CLI::showHelp(argv);
return !options.error ? 0 : 1;
}
json keys;
int status = CLI::validateCommandLine(&options, argv, &keys);
if (status > 0) {
return status;
}
CLI run(options, keys);
switch(options.applicationMode) {
case MODE_BINK1998_GENERATE:
return run.BINK1998Generate();
case MODE_BINK2002_GENERATE:
return run.BINK2002Generate();
case MODE_BINK1998_VALIDATE:
return run.BINK1998Validate();
case MODE_BINK2002_VALIDATE:
return run.BINK2002Validate();
case MODE_CONFIRMATION_ID:
return run.ConfirmationID();
default:
return 1;
}
}
+729
View File
@@ -0,0 +1,729 @@
#ifndef WINVER
#define WINVER 0x0400
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#ifndef NTDDI_VERSION
#define NTDDI_VERSION 0x04000000
#endif
#include <windows.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
extern int main(int argc, char **argv);
typedef void (*umskt_ctor)(void);
extern "C" umskt_ctor __init_array_start[] __attribute__((weak));
extern "C" umskt_ctor __init_array_end[] __attribute__((weak));
extern "C" void *memset(void *dst, int value, size_t count) {
unsigned char *bytes = (unsigned char *)dst;
unsigned char fill = (unsigned char)value;
while (count--) {
*bytes++ = fill;
}
return dst;
}
extern "C" void *memcpy(void *dst, const void *src, size_t count) {
unsigned char *out = (unsigned char *)dst;
const unsigned char *in = (const unsigned char *)src;
while (count--) {
*out++ = *in++;
}
return dst;
}
extern "C" void *memmove(void *dst, const void *src, size_t count) {
unsigned char *out = (unsigned char *)dst;
const unsigned char *in = (const unsigned char *)src;
size_t index;
if (out == in || count == 0) {
return dst;
}
if (out < in) {
for (index = 0; index < count; index++) {
out[index] = in[index];
}
} else {
index = count;
while (index > 0) {
index--;
out[index] = in[index];
}
}
return dst;
}
extern "C" int memcmp(const void *left, const void *right, size_t count) {
const unsigned char *a = (const unsigned char *)left;
const unsigned char *b = (const unsigned char *)right;
while (count--) {
if (*a != *b) {
return (int)*a - (int)*b;
}
a++;
b++;
}
return 0;
}
extern "C" size_t strlen(const char *text) {
size_t n = 0;
if (!text) {
return 0;
}
while (text[n]) {
n++;
}
return n;
}
extern "C" int strcmp(const char *a, const char *b) {
if (!a || !b) {
return a == b ? 0 : (a ? 1 : -1);
}
while (*a && *a == *b) {
a++;
b++;
}
return (unsigned char)*a - (unsigned char)*b;
}
extern "C" int strncmp(const char *a, const char *b, size_t n) {
while (n && *a && *a == *b) {
a++;
b++;
n--;
}
if (!n) {
return 0;
}
return (unsigned char)*a - (unsigned char)*b;
}
extern "C" char *strcpy(char *dst, const char *src) {
char *out = dst;
while ((*dst++ = *src++)) {
}
return out;
}
extern "C" char *strncpy(char *dst, const char *src, size_t n) {
size_t i = 0;
for (; i < n && src[i]; i++) {
dst[i] = src[i];
}
for (; i < n; i++) {
dst[i] = 0;
}
return dst;
}
extern "C" char *strchr(const char *text, int ch) {
if (!text) {
return NULL;
}
while (*text && *text != (char)ch) {
text++;
}
if (*text == (char)ch) {
return (char *)text;
}
return NULL;
}
extern "C" void *malloc(size_t size) {
if (size == 0) {
size = 1;
}
return HeapAlloc(GetProcessHeap(), 0, size);
}
extern "C" void *calloc(size_t count, size_t size) {
size_t bytes = count * size;
if (count != 0 && bytes / count != size) {
return NULL;
}
if (bytes == 0) {
bytes = 1;
}
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytes);
}
extern "C" void free(void *block) {
if (block) {
HeapFree(GetProcessHeap(), 0, block);
}
}
extern "C" void *realloc(void *block, size_t size) {
if (!block) {
return malloc(size);
}
if (size == 0) {
free(block);
return NULL;
}
return HeapReAlloc(GetProcessHeap(), 0, block, size);
}
extern "C" void abort(void) {
ExitProcess(3);
}
extern "C" int atexit(void (*function)(void)) {
(void)function;
return 0;
}
extern "C" int __cxa_atexit(void (*function)(void *), void *arg, void *dso) {
(void)function;
(void)arg;
(void)dso;
return 0;
}
extern "C" void __cxa_pure_virtual(void) {
ExitProcess(1);
}
void *operator new(size_t count) {
return malloc(count ? count : 1);
}
void *operator new[](size_t count) {
return malloc(count ? count : 1);
}
void operator delete(void *ptr) noexcept {
free(ptr);
}
void operator delete[](void *ptr) noexcept {
free(ptr);
}
void operator delete(void *ptr, size_t) noexcept {
free(ptr);
}
void operator delete[](void *ptr, size_t) noexcept {
free(ptr);
}
#if defined(__i386__)
extern "C" __attribute__((naked)) void __chkstk_ms(void) {
__asm__ __volatile__(
"pushl %ecx\n\t"
"pushl %eax\n\t"
"cmpl $0x1000, %eax\n\t"
"leal 12(%esp), %ecx\n\t"
"jb 1f\n\t"
"2:\n\t"
"subl $0x1000, %ecx\n\t"
"testl %eax, (%ecx)\n\t"
"subl $0x1000, %eax\n\t"
"cmpl $0x1000, %eax\n\t"
"ja 2b\n\t"
"1:\n\t"
"subl %eax, %ecx\n\t"
"testl %eax, (%ecx)\n\t"
"popl %eax\n\t"
"popl %ecx\n\t"
"ret\n\t");
}
static void udivmod64(uint32_t nlo, uint32_t nhi, uint32_t dlo, uint32_t dhi, uint32_t *qlo, uint32_t *qhi, uint32_t *rlo, uint32_t *rhi) {
uint32_t ql = 0;
uint32_t qh = 0;
uint32_t rl = 0;
uint32_t rh = 0;
int bit;
if (dlo == 0 && dhi == 0) {
*qlo = 0;
*qhi = 0;
*rlo = 0;
*rhi = 0;
return;
}
for (bit = 63; bit >= 0; bit--) {
uint32_t src = bit >= 32 ? nhi : nlo;
uint32_t src_bit = (src >> (bit >= 32 ? bit - 32 : bit)) & 1u;
rh = (rh << 1) | (rl >> 31);
rl = (rl << 1) | src_bit;
if (rh > dhi || (rh == dhi && rl >= dlo)) {
uint32_t new_rl = rl - dlo;
uint32_t borrow = rl < dlo;
rh = rh - dhi - borrow;
rl = new_rl;
if (bit >= 32) {
qh |= 1u << (bit - 32);
} else {
ql |= 1u << bit;
}
}
}
*qlo = ql;
*qhi = qh;
*rlo = rl;
*rhi = rh;
}
extern "C" unsigned long long __udivdi3(unsigned long long n, unsigned long long d) {
union {
unsigned long long v;
uint32_t p[2];
} N, D, Q;
uint32_t rlo, rhi;
N.v = n;
D.v = d;
udivmod64(N.p[0], N.p[1], D.p[0], D.p[1], &Q.p[0], &Q.p[1], &rlo, &rhi);
return Q.v;
}
extern "C" unsigned long long __umoddi3(unsigned long long n, unsigned long long d) {
union {
unsigned long long v;
uint32_t p[2];
} N, D, R;
uint32_t qlo, qhi;
N.v = n;
D.v = d;
udivmod64(N.p[0], N.p[1], D.p[0], D.p[1], &qlo, &qhi, &R.p[0], &R.p[1]);
return R.v;
}
extern "C" unsigned long long __udivmoddi4(unsigned long long n, unsigned long long d, unsigned long long *rem) {
unsigned long long quot = __udivdi3(n, d);
if (rem) {
*rem = __umoddi3(n, d);
}
return quot;
}
extern "C" long long __divdi3(long long a, long long b) {
int neg = 0;
unsigned long long ua;
unsigned long long ub;
unsigned long long uq;
if (a < 0) {
neg ^= 1;
ua = 0u - (unsigned long long)a;
} else {
ua = (unsigned long long)a;
}
if (b < 0) {
neg ^= 1;
ub = 0u - (unsigned long long)b;
} else {
ub = (unsigned long long)b;
}
uq = __udivdi3(ua, ub);
if (neg) {
uq = 0u - uq;
}
return (long long)uq;
}
extern "C" long long __moddi3(long long a, long long b) {
int neg = a < 0;
unsigned long long ua = a < 0 ? (0u - (unsigned long long)a) : (unsigned long long)a;
unsigned long long ub = b < 0 ? (0u - (unsigned long long)b) : (unsigned long long)b;
unsigned long long ur = __umoddi3(ua, ub);
if (neg) {
ur = 0u - ur;
}
return (long long)ur;
}
extern "C" long long __muldi3(long long a, long long b) {
union {
unsigned long long v;
uint32_t p[2];
} A, B, R;
uint64_t low;
uint64_t mid;
A.v = (unsigned long long)a;
B.v = (unsigned long long)b;
low = (uint64_t)A.p[0] * B.p[0];
mid = (low >> 32) + (uint64_t)A.p[0] * B.p[1] + (uint64_t)A.p[1] * B.p[0];
R.p[0] = (uint32_t)low;
R.p[1] = (uint32_t)mid;
return (long long)R.v;
}
extern "C" unsigned long long __lshrdi3(unsigned long long value, int amount) {
union {
unsigned long long v;
uint32_t p[2];
} u;
u.v = value;
if (amount <= 0) {
return value;
}
if (amount >= 64) {
u.p[0] = 0;
u.p[1] = 0;
return u.v;
}
if (amount >= 32) {
u.p[0] = u.p[1] >> (amount - 32);
u.p[1] = 0;
return u.v;
}
u.p[0] = (u.p[0] >> amount) | (u.p[1] << (32 - amount));
u.p[1] >>= amount;
return u.v;
}
extern "C" unsigned long long __ashldi3(unsigned long long value, int amount) {
union {
unsigned long long v;
uint32_t p[2];
} u;
u.v = value;
if (amount <= 0) {
return value;
}
if (amount >= 64) {
u.p[0] = 0;
u.p[1] = 0;
return u.v;
}
if (amount >= 32) {
u.p[1] = u.p[0] << (amount - 32);
u.p[0] = 0;
return u.v;
}
u.p[1] = (u.p[1] << amount) | (u.p[0] >> (32 - amount));
u.p[0] <<= amount;
return u.v;
}
extern "C" long long __ashrdi3(long long value, int amount) {
union {
unsigned long long v;
uint32_t p[2];
} u;
uint32_t lo;
uint32_t hi;
uint32_t sign;
u.v = (unsigned long long)value;
lo = u.p[0];
hi = u.p[1];
sign = hi & 0x80000000u;
if (amount <= 0) {
return value;
}
if (amount >= 64) {
u.p[0] = sign ? 0xFFFFFFFFu : 0;
u.p[1] = sign ? 0xFFFFFFFFu : 0;
return (long long)u.v;
}
if (amount >= 32) {
u.p[0] = (uint32_t)((int32_t)hi >> (amount - 32));
u.p[1] = sign ? 0xFFFFFFFFu : 0;
return (long long)u.v;
}
u.p[0] = (lo >> amount) | (hi << (32 - amount));
u.p[1] = (uint32_t)((int32_t)hi >> amount);
return (long long)u.v;
}
#elif defined(__x86_64__)
extern "C" __attribute__((naked)) void __chkstk_ms(void) {
__asm__ __volatile__(
"pushq %rcx\n\t"
"pushq %rax\n\t"
"cmpq $0x1000, %rax\n\t"
"leaq 24(%rsp), %rcx\n\t"
"jb 1f\n\t"
"2:\n\t"
"subq $0x1000, %rcx\n\t"
"testq %rax, (%rcx)\n\t"
"subq $0x1000, %rax\n\t"
"cmpq $0x1000, %rax\n\t"
"ja 2b\n\t"
"1:\n\t"
"subq %rax, %rcx\n\t"
"testq %rax, (%rcx)\n\t"
"popq %rax\n\t"
"popq %rcx\n\t"
"ret\n\t");
}
#endif
static int main_ctors_done = 0;
extern "C" void __main(void) {
umskt_ctor *ctor;
if (main_ctors_done) {
return;
}
main_ctors_done = 1;
if (!__init_array_start || !__init_array_end) {
return;
}
for (ctor = __init_array_start; ctor < __init_array_end; ctor++) {
if (*ctor) {
(*ctor)();
}
}
}
static void fmt_putc(char *dst, size_t cap, size_t *used, char ch) {
if (*used + 1 < cap) {
dst[*used] = ch;
}
(*used)++;
}
static void fmt_puts(char *dst, size_t cap, size_t *used, const char *text) {
if (!text) {
text = "(null)";
}
while (*text) {
fmt_putc(dst, cap, used, *text++);
}
}
static void fmt_pad(char *dst, size_t cap, size_t *used, const char *digits, int count, int width, int zero) {
int pad = width - count;
if (digits[0] == '-' && zero) {
fmt_putc(dst, cap, used, '-');
digits++;
count--;
pad = width - count - 1;
}
while (pad-- > 0) {
fmt_putc(dst, cap, used, zero ? '0' : ' ');
}
while (count-- > 0) {
fmt_putc(dst, cap, used, *digits++);
}
}
static void fmt_u64(char *dst, size_t cap, size_t *used, unsigned long long value, unsigned base, int upper, int width, int zero) {
char rev[72];
int count = 0;
const char *alphabet = upper ? "0123456789ABCDEF" : "0123456789abcdef";
if (value == 0) {
rev[count++] = '0';
}
while (value) {
rev[count++] = alphabet[value % base];
value /= base;
}
{
char forward[72];
int i;
for (i = 0; i < count; i++) {
forward[i] = rev[count - 1 - i];
}
forward[count] = 0;
fmt_pad(dst, cap, used, forward, count, width, zero);
}
}
static int umskt_vsnprintf(char *dst, size_t cap, const char *fmt, va_list ap) {
size_t used = 0;
if (!fmt) {
fmt = "";
}
while (*fmt) {
if (*fmt != '%') {
fmt_putc(dst, cap, &used, *fmt++);
continue;
}
fmt++;
if (*fmt == '%') {
fmt_putc(dst, cap, &used, '%');
fmt++;
continue;
}
int zero = 0;
int width = 0;
int is_long = 0;
if (*fmt == '0') {
zero = 1;
fmt++;
}
while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + (*fmt - '0');
fmt++;
}
if (*fmt == 'l') {
is_long = 1;
fmt++;
if (*fmt == 'l') {
fmt++;
}
}
if (*fmt == 's') {
fmt_puts(dst, cap, &used, va_arg(ap, const char *));
} else if (*fmt == 'c') {
fmt_putc(dst, cap, &used, (char)va_arg(ap, int));
} else if (*fmt == 'd' || *fmt == 'i') {
if (is_long) {
long long value = va_arg(ap, long long);
if (value < 0) {
unsigned long long mag = 0u - (unsigned long long)value;
char rev[72];
int count = 0;
char forward[72];
int i;
if (mag == 0) {
rev[count++] = '0';
}
while (mag) {
rev[count++] = (char)('0' + (mag % 10));
mag /= 10;
}
forward[0] = '-';
for (i = 0; i < count; i++) {
forward[i + 1] = rev[count - 1 - i];
}
fmt_pad(dst, cap, &used, forward, count + 1, width, zero);
} else {
fmt_u64(dst, cap, &used, (unsigned long long)value, 10, 0, width, zero);
}
} else {
int value = va_arg(ap, int);
if (value < 0) {
unsigned int mag = 0u - (unsigned int)value;
char rev[16];
char forward[16];
int count = 0;
int i;
while (mag) {
rev[count++] = (char)('0' + (mag % 10));
mag /= 10;
}
if (count == 0) {
rev[count++] = '0';
}
forward[0] = '-';
for (i = 0; i < count; i++) {
forward[i + 1] = rev[count - 1 - i];
}
fmt_pad(dst, cap, &used, forward, count + 1, width, zero);
} else {
fmt_u64(dst, cap, &used, (unsigned)value, 10, 0, width, zero);
}
}
} else if (*fmt == 'u') {
if (is_long) {
fmt_u64(dst, cap, &used, va_arg(ap, unsigned long long), 10, 0, width, zero);
} else {
fmt_u64(dst, cap, &used, va_arg(ap, unsigned int), 10, 0, width, zero);
}
} else if (*fmt == 'x' || *fmt == 'X') {
if (is_long) {
fmt_u64(dst, cap, &used, va_arg(ap, unsigned long long), 16, *fmt == 'X', width, zero);
} else {
fmt_u64(dst, cap, &used, va_arg(ap, unsigned int), 16, *fmt == 'X', width, zero);
}
} else if (*fmt) {
fmt_putc(dst, cap, &used, *fmt);
}
if (*fmt) {
fmt++;
}
}
if (cap > 0) {
size_t end = used < cap ? used : cap - 1;
dst[end] = 0;
}
return (int)used;
}
/* MinGW's stdio.h turns snprintf/vsnprintf into an inline that calls these. */
#ifdef snprintf
#undef snprintf
#endif
#ifdef vsnprintf
#undef vsnprintf
#endif
extern "C" int __mingw_vsnprintf(char *dst, size_t cap, const char *fmt, va_list ap) {
return umskt_vsnprintf(dst, cap, fmt, ap);
}
extern "C" int vsnprintf(char *dst, size_t cap, const char *fmt, va_list ap) {
return umskt_vsnprintf(dst, cap, fmt, ap);
}
extern "C" int snprintf(char *dst, size_t cap, const char *fmt, ...) {
va_list ap;
int count;
va_start(ap, fmt);
count = umskt_vsnprintf(dst, cap, fmt, ap);
va_end(ap);
return count;
}
static int is_space(char ch) {
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
}
extern "C" void mainCRTStartup(void) {
char *command = GetCommandLineA();
char *buffer;
char **argv;
int length = 0;
int argc = 0;
char *cursor;
HANDLE heap = GetProcessHeap();
__main();
if (!command) {
command = (char *)"";
}
while (command[length]) {
length++;
}
buffer = (char *)HeapAlloc(heap, 0, (SIZE_T)length + 1);
argv = (char **)HeapAlloc(heap, HEAP_ZERO_MEMORY, (SIZE_T)(length + 2) * sizeof(char *));
if (!buffer || !argv) {
ExitProcess(1);
}
for (int index = 0; index <= length; index++) {
buffer[index] = command[index];
}
cursor = buffer;
while (*cursor) {
char *out;
int quoted = 0;
int more;
while (is_space(*cursor)) {
cursor++;
}
if (!*cursor) {
break;
}
argv[argc++] = cursor;
out = cursor;
while (*cursor) {
if (*cursor == '"') {
quoted = !quoted;
cursor++;
continue;
}
if (!quoted && is_space(*cursor)) {
break;
}
*out++ = *cursor++;
}
more = *cursor != 0;
*out = 0;
if (more) {
cursor++;
}
}
argv[argc] = NULL;
ExitProcess((UINT)main(argc, argv));
}
+236
View File
@@ -0,0 +1,236 @@
/* This file is a part of the UMSKT Project.
*
* Copyleft (C) 2019-2026 UMSKT Contributors (et.al.)
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include "json.h"
struct JsonCursor {
const char *begin;
const char *p;
const char *end;
};
static void skip_ws(JsonCursor *j) {
while (j->p < j->end) {
char ch = *j->p;
if (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r') {
break;
}
j->p++;
}
}
static int skip_string(JsonCursor *j) {
if (j->p >= j->end || *j->p != '"') {
return 0;
}
j->p++;
while (j->p < j->end) {
char ch = *j->p++;
if (ch == '\\') {
if (j->p < j->end) {
j->p++;
}
continue;
}
if (ch == '"') {
return 1;
}
}
return 0;
}
static int skip_value(JsonCursor *j) {
skip_ws(j);
if (j->p >= j->end) {
return 0;
}
if (*j->p == '"') {
return skip_string(j);
}
if (*j->p == '{' || *j->p == '[') {
char open = *j->p;
char close = open == '{' ? '}' : ']';
int depth = 0;
while (j->p < j->end) {
if (*j->p == '"') {
if (!skip_string(j)) {
return 0;
}
continue;
}
if (*j->p == open) {
depth++;
} else if (*j->p == close) {
depth--;
j->p++;
if (depth == 0) {
return 1;
}
continue;
}
j->p++;
}
return 0;
}
while (j->p < j->end) {
char ch = *j->p;
if (ch == ',' || ch == '}' || ch == ']' || ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
break;
}
j->p++;
}
return 1;
}
static int parse_key(JsonCursor *j, const char **key, int *key_length) {
const char *start;
skip_ws(j);
if (j->p >= j->end || *j->p != '"') {
return 0;
}
j->p++;
start = j->p;
while (j->p < j->end && *j->p != '"') {
if (*j->p == '\\') {
return 0;
}
j->p++;
}
if (j->p >= j->end) {
return 0;
}
*key = start;
*key_length = (int)(j->p - start);
j->p++;
return 1;
}
static int key_eq(const char *key, int key_length, const char *wanted) {
int i = 0;
while (wanted[i] && i < key_length) {
if (key[i] != wanted[i]) {
return 0;
}
i++;
}
return wanted[i] == 0 && i == key_length;
}
int json_object_find(const char *object, int length, const char *key, JsonSpan *value) {
JsonCursor j;
j.begin = object;
j.p = object;
j.end = object + length;
skip_ws(&j);
if (j.p >= j.end || *j.p != '{') {
return 0;
}
j.p++;
while (j.p < j.end) {
const char *found;
int found_len;
skip_ws(&j);
if (j.p < j.end && *j.p == '}') {
return 0;
}
if (!parse_key(&j, &found, &found_len)) {
return 0;
}
skip_ws(&j);
if (j.p >= j.end || *j.p != ':') {
return 0;
}
j.p++;
skip_ws(&j);
if (key_eq(found, found_len, key)) {
const char *start = j.p;
if (!skip_value(&j)) {
return 0;
}
value->p = start;
value->n = (int)(j.p - start);
return 1;
}
if (!skip_value(&j)) {
return 0;
}
skip_ws(&j);
if (j.p < j.end && *j.p == ',') {
j.p++;
}
}
return 0;
}
int json_unquote(const JsonSpan *value, const char **text, int *length) {
const char *p;
const char *end;
if (!value || value->n < 2 || value->p[0] != '"') {
return 0;
}
p = value->p + 1;
end = value->p + value->n;
if (end[-1] != '"') {
return 0;
}
*text = p;
*length = (int)(end - p - 1);
return 1;
}
static int next_member(const char *text, int length, int *cursor, int array, const char **key, int *key_length, JsonSpan *value) {
JsonCursor j;
const char *open;
j.begin = text;
j.end = text + length;
if (*cursor == 0) {
j.p = text;
skip_ws(&j);
if (j.p >= j.end || *j.p != (array ? '[' : '{')) {
return 0;
}
j.p++;
*cursor = (int)(j.p - text);
}
j.p = text + *cursor;
skip_ws(&j);
if (j.p >= j.end || *j.p == (array ? ']' : '}')) {
return 0;
}
if (!array) {
if (!parse_key(&j, key, key_length)) {
return 0;
}
skip_ws(&j);
if (j.p >= j.end || *j.p != ':') {
return 0;
}
j.p++;
skip_ws(&j);
}
open = j.p;
if (!skip_value(&j)) {
return 0;
}
value->p = open;
value->n = (int)(j.p - open);
skip_ws(&j);
if (j.p < j.end && *j.p == ',') {
j.p++;
}
*cursor = (int)(j.p - text);
return 1;
}
int json_object_next(const char *object, int length, int *cursor, const char **key, int *key_length, JsonSpan *value) {
return next_member(object, length, cursor, 0, key, key_length, value);
}
int json_array_next(const char *array, int length, int *cursor, JsonSpan *value) {
const char *ignored = 0;
int ignored_len = 0;
return next_member(array, length, cursor, 1, &ignored, &ignored_len, value);
}
+29
View File
@@ -0,0 +1,29 @@
/* This file is a part of the UMSKT Project.
*
* Copyleft (C) 2019-2026 UMSKT Contributors (et.al.)
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* Walks the keys.json object shape. Strings are spans into the source buffer.
*/
#ifndef UMSKT_WIN_JSON_H
#define UMSKT_WIN_JSON_H
struct JsonSpan {
const char *p;
int n;
};
/* Find a direct child of an object. `object` includes the surrounding braces. */
int json_object_find(const char *object, int length, const char *key, JsonSpan *value);
/* If value is a JSON string, point at the unquoted bytes. They are not NUL-terminated. */
int json_unquote(const JsonSpan *value, const char **text, int *length);
/* Iterate direct children. *cursor starts at 0 and is updated. Returns 0 when finished. */
int json_object_next(const char *object, int length, int *cursor, const char **key, int *key_length, JsonSpan *value);
/* Iterate array elements. *cursor starts at 0. */
int json_array_next(const char *array, int length, int *cursor, JsonSpan *value);
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef UMSKT_WIN32_MIN_H
#define UMSKT_WIN32_MIN_H
#include <stdint.h>
#define UMSKT_STD_INPUT_HANDLE ((uint32_t)-10)
#define UMSKT_STD_OUTPUT_HANDLE ((uint32_t)-11)
#define UMSKT_STD_ERROR_HANDLE ((uint32_t)-12)
#define UMSKT_INVALID_HANDLE ((void *)(intptr_t)-1)
#define UMSKT_GENERIC_READ 0x80000000u
#define UMSKT_FILE_SHARE_READ 1u
#define UMSKT_OPEN_EXISTING 3u
#define UMSKT_FILE_ATTRIBUTE_NORMAL 0x80u
#define UMSKT_INVALID_FILE_SIZE 0xFFFFFFFFu
#define UMSKT_RT_RCDATA ((const char *)(uintptr_t)10)
extern "C" {
__declspec(dllimport) void *__stdcall GetStdHandle(uint32_t);
__declspec(dllimport) int __stdcall WriteFile(void *, const void *, uint32_t, uint32_t *, void *);
__declspec(dllimport) int __stdcall ReadFile(void *, void *, uint32_t, uint32_t *, void *);
__declspec(dllimport) void *__stdcall CreateFileA(const char *, uint32_t, uint32_t, void *, uint32_t, uint32_t, void *);
__declspec(dllimport) int __stdcall CloseHandle(void *);
__declspec(dllimport) uint32_t __stdcall GetFileSize(void *, uint32_t *);
__declspec(dllimport) void *__stdcall FindResourceA(void *, const char *, const char *);
__declspec(dllimport) uint32_t __stdcall SizeofResource(void *, void *);
__declspec(dllimport) void *__stdcall LoadResource(void *, void *);
__declspec(dllimport) void *__stdcall LockResource(void *);
}
#endif
+168
View File
@@ -0,0 +1,168 @@
param(
[Parameter(Mandatory = $true)][string]$Exe,
[Parameter(Mandatory = $true)][string]$Objdump,
[Parameter(Mandatory = $true)][ValidateSet("x86", "x64")][string]$Arch
)
$ErrorActionPreference = "Stop"
function Fail([string]$Message) {
Write-Host "Windows baseline check failed: $Message"
exit 1
}
if (-not (Test-Path -LiteralPath $Exe)) {
Fail "missing binary: $Exe"
}
if (-not (Test-Path -LiteralPath $Objdump)) {
Fail "missing objdump: $Objdump"
}
$format = & $Objdump -f -- $Exe 2>&1 | Out-String
if ($LASTEXITCODE -ne 0) {
Fail "objdump -f failed: $format"
}
$expectFormat = $(if ($Arch -eq "x86") { "pei-i386" } else { "pei-x86-64" })
if ($format -notmatch [regex]::Escape($expectFormat)) {
Fail "expected a $expectFormat binary"
}
$pe = & $Objdump -p -- $Exe 2>&1 | Out-String
if ($LASTEXITCODE -ne 0) {
Fail "objdump -p failed: $pe"
}
function PeField([string]$Text, [string]$Name) {
if ($Text -match ("(?m)^\s*" + [regex]::Escape($Name) + "\s+(\d+)")) {
return [int]$Matches[1]
}
return $null
}
$osMajor = PeField $pe "MajorOSystemVersion"
$osMinor = PeField $pe "MinorOSystemVersion"
$subMajor = PeField $pe "MajorSubsystemVersion"
$subMinor = PeField $pe "MinorSubsystemVersion"
if ($Arch -eq "x86") {
if ($osMajor -ne 4 -or $osMinor -ne 0 -or $subMajor -ne 4 -or $subMinor -ne 0) {
Fail "expected Windows 98 / NT 4 subsystem 4.0, got OS $osMajor.$osMinor subsystem $subMajor.$subMinor"
}
} else {
if ($osMajor -ne 5 -or $osMinor -ne 2 -or $subMajor -ne 5 -or $subMinor -ne 2) {
Fail "expected XP x64 subsystem 5.2, got OS $osMajor.$osMinor subsystem $subMajor.$subMinor"
}
}
$allowedDlls = @{
"kernel32.dll" = $true
}
$badImports = @{
"encodepointer" = $true
"decodepointer" = $true
"encodesystempointer" = $true
"decodesystempointer" = $true
"gettickcount64" = $true
"initializecriticalsectionex" = $true
"flsalloc" = $true
"flsfree" = $true
"flsgetvalue" = $true
"flssetvalue" = $true
"comparestringex" = $true
"lcmapstringex" = $true
"getlocaleinfoex" = $true
"lcidtolocalename" = $true
"localenametolcid" = $true
"initializeconditionvariable" = $true
"sleepconditionvariablecs" = $true
"sleepconditionvariablesrw" = $true
"wakeconditionvariable" = $true
"wakeallconditionvariable" = $true
"initializesrwlock" = $true
"acquiresrwlockexclusive" = $true
"releasesrwlockexclusive" = $true
"tryacquiresrwlockexclusive" = $true
"getfileinformationbyhandleex" = $true
"setfileinformationbyhandle" = $true
"getfinalpathnamebyhandlea" = $true
"getfinalpathnamebyhandlew" = $true
"createsymboliclinka" = $true
"createsymboliclinkw" = $true
"getmodulehandleexa" = $true
"getmodulehandleexw" = $true
"iswow64process" = $true
"interlockedcompareexchange64" = $true
"heapsetinformation" = $true
"__getmainargs" = $true
"__wgetmainargs" = $true
"__set_app_type" = $true
"_amsg_exit" = $true
"__p__fmode" = $true
"__p__commode" = $true
"__p__environ" = $true
"getnativesysteminfo" = $true
"createtoolhelp32snapshot" = $true
"process32first" = $true
"process32firsta" = $true
"process32firstw" = $true
"process32next" = $true
"process32nexta" = $true
"process32nextw" = $true
"loadlibraryw" = $true
}
$importHits = New-Object System.Collections.Generic.List[string]
foreach ($line in ($pe -split "`r?`n")) {
if ($line -match "DLL Name:\s*(\S+)") {
$dll = $Matches[1]
if (-not $allowedDlls.ContainsKey($dll.ToLowerInvariant())) {
$importHits.Add("DLL $dll")
}
}
if ($line -match "^\s+[0-9A-Fa-f]+\s+[0-9A-Fa-f]+\s+(\S+)") {
$name = $Matches[1]
if ($name -match "^(.*)@\d+$") {
$name = $Matches[1]
}
if ($badImports.ContainsKey($name.ToLowerInvariant())) {
$importHits.Add($name)
}
}
}
if ($importHits.Count -gt 0) {
$shown = ($importHits | Select-Object -First 20) -join ", "
Fail "imports outside kernel32, or APIs missing on Windows 98 / NT 4: $shown"
}
if ($Arch -eq "x86") {
$badMnemonic = "(?i)^(cmov[a-z]*|fcmov[a-z]*|emms|nopl|nopw|fcomi|fcomip|fucomi|fucomip|movaps|movups|movapd|movupd|movdqa|movdqu|movss|movhps|movlps|movlhps|movhlps|xorps|xorpd|andps|andpd|orps|orpd|addps|addpd|addss|addsd|subps|subpd|subss|subsd|mulps|mulpd|mulss|mulsd|divps|divpd|divss|divsd|cvtsi2ss|cvtsi2sd|cvttss2si|cvttsd2si|cvtss2si|cvtsd2si|pshufd|pshuflw|pshufhw|pshufw|punpck[a-z]+|packss[a-z]+|packus[a-z]+|pcmp[a-z]+|padd[bwdq]|psub[bwdq]|pmullw|pmulhw|pmulhuw|pmaddwd|pavgb|pavgw|pextrw|pinsrw|pmovmskb|prefetch[a-z]*|sfence|mfence|lfence|maskmovq|movntq|movntps|lddqu|pause)\b"
$badRegister = "(?i)%(mm|xmm|ymm|zmm)[0-9]"
$insnHits = New-Object System.Collections.Generic.List[string]
$disasm = & $Objdump -d -M att -- $Exe 2>&1
if ($LASTEXITCODE -ne 0) {
Fail "objdump -d failed"
}
foreach ($line in $disasm) {
$text = [string]$line
$insn = $null
if ($text.Contains("`t")) {
$parts = $text.Split("`t")
$insn = $parts[$parts.Length - 1].Trim()
}
if (-not $insn) {
continue
}
if ($insn -match $badMnemonic -or $insn -match $badRegister) {
$insnHits.Add($text.Trim())
if ($insnHits.Count -ge 20) {
break
}
}
}
if ($insnHits.Count -gt 0) {
Fail ("forbidden instructions:`n" + ($insnHits -join "`n"))
}
}
Write-Host "Windows baseline check passed ($Arch, kernel32 only): $Exe"
exit 0