mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-07-03 19:52:47 -05:00
Compare commits
245 Commits
Author | SHA1 | Date | |
---|---|---|---|
76ee550c9d | |||
2b3228d549 | |||
bad6e96e0f | |||
3c8c74a8c3 | |||
771014a41e | |||
476168e09e | |||
be4f010535 | |||
2c27e2e37d | |||
b829e7a802 | |||
d0ae214cb4 | |||
9b1a6c9fb8 | |||
41b662a8fe | |||
5232734071 | |||
996cf20fa9 | |||
825c9dad7c | |||
6e5bef14e9 | |||
a53bd2bdb3 | |||
e4d471b885 | |||
bcb9737dda | |||
7a5389b719 | |||
d9f0a8dade | |||
aa8c8dd720 | |||
16c5e5aa4a | |||
ded1f7aa67 | |||
6ad2679f17 | |||
4776f43f04 | |||
d9db038c65 | |||
e8ef027776 | |||
0a0761746f | |||
f51e2a4869 | |||
093ed12c66 | |||
71a046a2d0 | |||
c73f82b558 | |||
b294f5d18f | |||
e07bb7d6b2 | |||
699bc85d0a | |||
192e7a732b | |||
656051676f | |||
3998bcabb2 | |||
fa40c57f80 | |||
0b93a94ffa | |||
105fd3af4a | |||
86a594b087 | |||
1dea73b038 | |||
b661ed08ed | |||
ead0584611 | |||
bd7751147e | |||
1bc7fc36b8 | |||
42e9733916 | |||
b2024cee9d | |||
9d152b8477 | |||
7a02d51a83 | |||
dac68a3a4d | |||
bd1ab77f44 | |||
5ee859db2c | |||
ee3c51f6d5 | |||
cedb8b5798 | |||
dcf58a00e7 | |||
4576895718 | |||
1bdcad619e | |||
31b046cf98 | |||
f3ac2c0c6f | |||
f22c83514c | |||
44ca1f38e6 | |||
0985c47990 | |||
aa158e40ec | |||
5da62de5ef | |||
4d08fbb2c1 | |||
98b004edda | |||
34bf3bc525 | |||
64e1bba96b | |||
46bcaa9d88 | |||
867e0d446d | |||
7285778cb0 | |||
c909ba82d7 | |||
7b60d6447d | |||
588a1a0b5f | |||
8a9b275494 | |||
0db17be606 | |||
f9ad19d4a2 | |||
b9ca24d423 | |||
8d2b562244 | |||
6f4e9ab597 | |||
6d6270094e | |||
57563716d1 | |||
8ab8a133f7 | |||
ef5047038e | |||
e290e03341 | |||
900ffed596 | |||
33253afb5e | |||
3aba55e5e0 | |||
898a53b2a7 | |||
75ce1dadf5 | |||
4166476030 | |||
a5690f2d19 | |||
cdb75578e9 | |||
e2ab4a152d | |||
b8e690f3bd | |||
c89d6b43aa | |||
9faed39931 | |||
ecb17709fc | |||
9ebd79ad18 | |||
1700455533 | |||
a6f767f5a3 | |||
4c5b329bc4 | |||
5626482e82 | |||
2d21a2121c | |||
5d2bf2c80f | |||
5b8376ce32 | |||
1fc2c937f2 | |||
2ed54490a6 | |||
a096aa8a33 | |||
aa08566a63 | |||
c04b229ce2 | |||
adcfd9a33f | |||
f2f3a8891c | |||
29eedf9059 | |||
d6f94d71f7 | |||
a509a66c65 | |||
7bf4c92d83 | |||
0a0fdfe96a | |||
199f2b4586 | |||
a92c4a5522 | |||
dc44ed5f5b | |||
c6990878c2 | |||
abbbfabdc7 | |||
2a4b75842a | |||
56e7a72e8a | |||
b61bcaac2e | |||
924af9e783 | |||
cb80c7d188 | |||
76bb06bf7e | |||
4b6027a4f7 | |||
de6a65cc67 | |||
c90166ba8d | |||
b00ceee310 | |||
54e61cb76a | |||
fb731f2b5e | |||
eec5a0755d | |||
41d98c3917 | |||
7fa0b21ddd | |||
e0eb331baf | |||
7bb21c3539 | |||
edcb18d63f | |||
3d7b8d2a21 | |||
7bfe3b5db9 | |||
dd365d68c4 | |||
09555e8c05 | |||
e4aa06f0c0 | |||
46e9ee447f | |||
3e7247d9dc | |||
d2f1b9c035 | |||
4199310cdf | |||
0204d04a25 | |||
246f0abbfc | |||
0f51a06b8f | |||
44a6768089 | |||
93f5f800d6 | |||
4db6ed0cad | |||
32b65659be | |||
8e74a05b40 | |||
83e47e0252 | |||
41e6042c26 | |||
33c1fdaa85 | |||
11eb76d4f3 | |||
b0391244a6 | |||
83f6ceeaea | |||
b96a7a2232 | |||
ff8034af2e | |||
bde67ec1e2 | |||
c5ad70d31a | |||
27a2a2bfa3 | |||
827f167f8b | |||
4098a5efc7 | |||
e88bc1ca14 | |||
dd2aaf0804 | |||
08113a08cb | |||
29843ccf40 | |||
5fef4faf47 | |||
5981c740c9 | |||
f3af509973 | |||
c29e14e697 | |||
4da5526c05 | |||
4ec23dbaa5 | |||
d9979c4bc6 | |||
695892b8bf | |||
192ff59916 | |||
506daf84ac | |||
bb6322e378 | |||
b0eaa96d45 | |||
fade782e58 | |||
199a852c12 | |||
95a8a9d9c1 | |||
c197d7727c | |||
efbe570f27 | |||
fef65536f6 | |||
1155a9c338 | |||
f67ca8aac5 | |||
d59601f2b9 | |||
7f87f930f7 | |||
dadca2516d | |||
a862378280 | |||
c4ec6debe5 | |||
08c205a02f | |||
acfece2c26 | |||
61cf89f26f | |||
07a927f34a | |||
257cb1fb08 | |||
c48a6cdef0 | |||
8bba4496c0 | |||
dfc13c9bf8 | |||
f57b469c29 | |||
c718882ffb | |||
3109bdf0ab | |||
7aca21b481 | |||
8c113b3a86 | |||
f3a5ecce9c | |||
1c678bf926 | |||
454e15326d | |||
db556d0a2d | |||
8bdd22c183 | |||
cc4e5a5076 | |||
b8cb44fa47 | |||
36cdea56de | |||
77e63fa0cb | |||
225ce9bbd6 | |||
a5011a00c5 | |||
f9006f099a | |||
b9664394a5 | |||
68c4163332 | |||
c143eff68f | |||
cbdbd9dbd0 | |||
20bfc0ffeb | |||
8e075d625d | |||
4eeaee4c16 | |||
6da29943ea | |||
431d6ab1bd | |||
5d51f0e2c7 | |||
4d476213d4 | |||
21c196342f | |||
b8d83bb15e | |||
abf5aa68f8 | |||
762dd8a21b | |||
86e4eb9252 | |||
7510e3c553 |
162
.github/workflows/ci.yml
vendored
162
.github/workflows/ci.yml
vendored
@ -7,6 +7,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
|
version: osslsigncode-2.9
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -14,87 +15,144 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- triplet: x64-linux
|
- id: ubuntu-24.04
|
||||||
os: ubuntu-latest
|
triplet: x64-linux
|
||||||
vcpkg_root: /usr/local/share/vcpkg
|
compiler: gcc
|
||||||
- triplet: x64-osx
|
os: ubuntu-24.04
|
||||||
|
generator: Unix Makefiles
|
||||||
|
vcpkg_root:
|
||||||
|
- id: ubuntu-22.04
|
||||||
|
triplet: x64-linux
|
||||||
|
compiler: gcc
|
||||||
|
os: ubuntu-22.04
|
||||||
|
generator: Unix Makefiles
|
||||||
|
vcpkg_root:
|
||||||
|
- id: ubuntu-20.04
|
||||||
|
triplet: x64-linux
|
||||||
|
compiler: gcc
|
||||||
|
os: ubuntu-20.04
|
||||||
|
generator: Unix Makefiles
|
||||||
|
vcpkg_root:
|
||||||
|
- id: macOS
|
||||||
|
triplet: x64-osx
|
||||||
|
compiler: clang
|
||||||
os: macOS-latest
|
os: macOS-latest
|
||||||
|
generator: Unix Makefiles
|
||||||
vcpkg_root: /usr/local/share/vcpkg
|
vcpkg_root: /usr/local/share/vcpkg
|
||||||
cache: /Users/runner/.cache/vcpkg/archives
|
cache: /Users/runner/.cache/vcpkg/archives
|
||||||
- triplet: x64-windows
|
- id: windows-x64-vs
|
||||||
|
triplet: x64-windows
|
||||||
|
compiler: vs
|
||||||
arch: x64
|
arch: x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
vcpkg_root: C:/vcpkg
|
vcpkg_root: C:/vcpkg
|
||||||
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
- triplet: x86-windows
|
- id: windows-x86-vs
|
||||||
|
triplet: x86-windows
|
||||||
|
compiler: vs
|
||||||
arch: x86
|
arch: x86
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
vcpkg_root: C:/vcpkg
|
vcpkg_root: C:/vcpkg
|
||||||
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
- triplet: x64-windows-static
|
- id: windows-x64-static-vs
|
||||||
|
triplet: x64-windows-static
|
||||||
|
compiler: vs
|
||||||
arch: x64
|
arch: x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
|
vcpkg_root: C:/vcpkg
|
||||||
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
|
- id: windows-x64-mingw
|
||||||
|
triplet: x64-windows
|
||||||
|
compiler: mingw
|
||||||
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
vcpkg_root: C:/vcpkg
|
vcpkg_root: C:/vcpkg
|
||||||
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
|
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
|
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{matrix.vcpkg_root}}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Cache the vcpkg archives
|
- name: Cache the vcpkg archives
|
||||||
if: matrix.os != 'ubuntu-latest'
|
if: matrix.cache != ''
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ${{matrix.cache}}
|
path: ${{matrix.cache}}
|
||||||
key: ${{matrix.triplet}}-${{hashFiles('vcpkg.json')}}
|
key: ${{matrix.id}}-${{hashFiles('vcpkg.json')}}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{matrix.triplet}}-${{hashFiles('vcpkg.json')}}
|
${{matrix.id}}-${{hashFiles('vcpkg.json')}}
|
||||||
${{matrix.triplet}}-
|
${{matrix.id}}-
|
||||||
|
|
||||||
- name: Configure VS Toolchain (Windows)
|
- name: Configure Visual Studio
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.compiler == 'vs'
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
with:
|
with:
|
||||||
arch: ${{matrix.arch}}
|
arch: ${{matrix.arch}}
|
||||||
|
|
||||||
|
- name: Install MSYS2
|
||||||
|
if: matrix.compiler == 'mingw'
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
update: true
|
||||||
|
install: mingw-w64-x86_64-ninja
|
||||||
|
|
||||||
|
- name: Put MSYS2_MinGW64 on PATH
|
||||||
|
if: matrix.compiler == 'mingw'
|
||||||
|
run: echo "D:/a/_temp/msys64/mingw64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
|
||||||
- name: Install apt dependencies (Linux)
|
- name: Install apt dependencies (Linux)
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: runner.os == 'Linux'
|
||||||
run: sudo apt-get install -y libssl-dev libcurl4-openssl-dev faketime
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get remove needrestart || echo Ignored
|
||||||
|
sudo apt-get install -y libssl-dev zlib1g-dev python3-cryptography
|
||||||
|
|
||||||
|
- name: Install brew dependencies (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
brew install python@3.8
|
||||||
|
|
||||||
|
- name: Install Xcode (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
uses: maxim-lobanov/setup-xcode@v1
|
||||||
|
with:
|
||||||
|
xcode-version: latest-stable
|
||||||
|
|
||||||
- name: Setup the oldest supported version of cmake (macOS)
|
- name: Setup the oldest supported version of cmake (macOS)
|
||||||
if: matrix.os == 'macOS-latest'
|
if: runner.os == 'macOS'
|
||||||
uses: jwlawson/actions-setup-cmake@v1.12
|
uses: jwlawson/actions-setup-cmake@v2.0
|
||||||
with:
|
with:
|
||||||
cmake-version: '3.17.0'
|
cmake-version: '3.17.0'
|
||||||
|
|
||||||
- name: Configure CMake (Linux)
|
- name: Install python3 cryptography module (macOS)
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: runner.os == 'macOS'
|
||||||
run: cmake
|
run: |
|
||||||
-S ${{github.workspace}}
|
python3.8 -m ensurepip
|
||||||
-B ${{github.workspace}}/build
|
python3.8 -m pip install --upgrade pip
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
python3.8 -m pip install cryptography
|
||||||
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
|
||||||
|
|
||||||
- name: Configure CMake (macOS)
|
- name: Install python3 cryptography module (Windows)
|
||||||
if: matrix.os == 'macOS-latest'
|
if: runner.os == 'Windows'
|
||||||
run: cmake
|
run: |
|
||||||
-S ${{github.workspace}}
|
C:/hostedtoolcache/windows/Python/3.12.3/x64/python3.exe -m ensurepip
|
||||||
-B ${{github.workspace}}/build
|
C:/hostedtoolcache/windows/Python/3.12.3/x64/python.exe -m pip install --upgrade pip
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
C:/hostedtoolcache/windows/Python/3.12.3/x64/python.exe -m pip install cryptography
|
||||||
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{matrix.vcpkg_root}}/scripts/buildsystems/vcpkg.cmake
|
|
||||||
-DVCPKG_TARGET_TRIPLET=${{matrix.triplet}}
|
|
||||||
|
|
||||||
- name: Configure CMake (Windows)
|
- name: Configure CMake
|
||||||
if: matrix.os == 'windows-latest'
|
|
||||||
run: cmake
|
run: cmake
|
||||||
-G Ninja
|
-G "${{matrix.generator}}"
|
||||||
-S ${{github.workspace}}
|
-S ${{github.workspace}}
|
||||||
-B ${{github.workspace}}/build
|
-B ${{github.workspace}}/build
|
||||||
|
-DCMAKE_OSX_ARCHITECTURES=arm64
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||||
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{matrix.vcpkg_root}}/scripts/buildsystems/vcpkg.cmake
|
|
||||||
-DVCPKG_TARGET_TRIPLET=${{matrix.triplet}}
|
-DVCPKG_TARGET_TRIPLET=${{matrix.triplet}}
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -102,12 +160,20 @@ jobs:
|
|||||||
--build ${{github.workspace}}/build
|
--build ${{github.workspace}}/build
|
||||||
--config ${{env.BUILD_TYPE}}
|
--config ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
- name: Show python version (macOS)
|
||||||
|
working-directory: ${{github.workspace}}/build
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
python3.8 --version
|
||||||
|
python3.8 -c "import sys; print(sys.executable)"
|
||||||
|
python3.8 -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
|
||||||
|
|
||||||
- name: List files (Linux/macOS)
|
- name: List files (Linux/macOS)
|
||||||
if: matrix.os != 'windows-latest'
|
if: runner.os != 'Windows'
|
||||||
run: find .. -ls
|
run: find .. -ls
|
||||||
|
|
||||||
- name: List files (Windows)
|
- name: List files (Windows)
|
||||||
if: matrix.os == 'windows-latest'
|
if: runner.os == 'Windows'
|
||||||
run: Get-ChildItem -Recurse -Name ..
|
run: Get-ChildItem -Recurse -Name ..
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
@ -115,17 +181,21 @@ jobs:
|
|||||||
run: ctest -C ${{env.BUILD_TYPE}}
|
run: ctest -C ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
- name: Upload the errors
|
- name: Upload the errors
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: errors-${{matrix.triplet}}
|
name: errors-${{matrix.id}}
|
||||||
path: ${{github.workspace}}/build/Testing/Temporary/LastTest.log
|
path: |
|
||||||
|
${{github.workspace}}/build/Testing/Temporary/LastTest.log
|
||||||
|
${{github.workspace}}/build/Testing/conf/makecerts.log
|
||||||
|
${{github.workspace}}/build/Testing/logs/server.log
|
||||||
|
${{github.workspace}}/build/Testing/logs/port.log
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: cmake --install ${{github.workspace}}/build
|
run: cmake --install ${{github.workspace}}/build
|
||||||
|
|
||||||
- name: Upload the executables
|
- name: Upload the executables
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: osslsigncode-${{matrix.triplet}}
|
name: ${{env.version}}-${{matrix.id}}
|
||||||
path: ${{github.workspace}}/dist
|
path: ${{github.workspace}}/dist
|
||||||
|
59
.github/workflows/codeql-analysis.yml
vendored
Normal file
59
.github/workflows/codeql-analysis.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "master" ]
|
||||||
|
schedule:
|
||||||
|
- cron: '45 1 * * 2'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'cpp' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
|
|
||||||
|
# - run: |
|
||||||
|
# echo "Run, Build Application using script"
|
||||||
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
26
.github/workflows/coverity.yml
vendored
Normal file
26
.github/workflows/coverity.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
name: Coverity Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverity:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
token: ${{secrets.COVERITY_SCAN_TOKEN}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
if: env.token
|
||||||
|
- name: Get ready for scanning
|
||||||
|
if: env.token
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libssl-dev libcurl4-openssl-dev
|
||||||
|
cmake -S ${{github.workspace}} -B ${{github.workspace}}/build
|
||||||
|
- uses: vapier/coverity-scan-action@v1
|
||||||
|
if: env.token
|
||||||
|
with:
|
||||||
|
email: ${{secrets.COVERITY_SCAN_EMAIL}}
|
||||||
|
token: ${{secrets.COVERITY_SCAN_TOKEN}}
|
||||||
|
command: make -C ${{github.workspace}}/build
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,7 +12,6 @@ CPackSourceConfig.cmake
|
|||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
Makefile
|
Makefile
|
||||||
missing
|
|
||||||
osslsigncode
|
osslsigncode
|
||||||
osslsigncode.exe
|
osslsigncode.exe
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
@ -3,15 +3,14 @@ cmake_minimum_required(VERSION 3.17)
|
|||||||
|
|
||||||
# autodetect vcpkg CMAKE_TOOLCHAIN_FILE if VCPKG_ROOT is defined
|
# autodetect vcpkg CMAKE_TOOLCHAIN_FILE if VCPKG_ROOT is defined
|
||||||
# this needs to be configured before the project() directive
|
# this needs to be configured before the project() directive
|
||||||
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
if((CMAKE_GENERATOR MATCHES "Ninja") AND DEFINED ENV{VCPKG_ROOT} AND NOT $ENV{VCPKG_ROOT} STREQUAL "" AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||||
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
|
||||||
CACHE STRING "")
|
endif((CMAKE_GENERATOR MATCHES "Ninja") AND DEFINED ENV{VCPKG_ROOT} AND NOT $ENV{VCPKG_ROOT} STREQUAL "" AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||||
endif(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
|
||||||
set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
||||||
|
|
||||||
# configure basic project information
|
# configure basic project information
|
||||||
project(osslsigncode
|
project(osslsigncode
|
||||||
VERSION 2.4
|
VERSION 2.9
|
||||||
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT and MSI files"
|
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT and MSI files"
|
||||||
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
||||||
LANGUAGES C)
|
LANGUAGES C)
|
||||||
@ -30,7 +29,10 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
|||||||
|
|
||||||
# load CMake library modules
|
# load CMake library modules
|
||||||
include(FindOpenSSL)
|
include(FindOpenSSL)
|
||||||
|
if(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
include(FindCURL)
|
include(FindCURL)
|
||||||
|
endif(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
|
include(FindZLIB)
|
||||||
|
|
||||||
# load CMake project modules
|
# load CMake project modules
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
@ -48,10 +50,10 @@ configure_file(Config.h.in config.h)
|
|||||||
target_compile_definitions(osslsigncode PRIVATE HAVE_CONFIG_H=1)
|
target_compile_definitions(osslsigncode PRIVATE HAVE_CONFIG_H=1)
|
||||||
|
|
||||||
# set sources
|
# set sources
|
||||||
target_sources(osslsigncode PRIVATE osslsigncode.c msi.c)
|
target_sources(osslsigncode PRIVATE osslsigncode.c helpers.c utf.c msi.c pe.c cab.c cat.c appx.c script.c)
|
||||||
if(WIN32)
|
if(NOT UNIX)
|
||||||
target_sources(osslsigncode PRIVATE applink.c)
|
target_sources(osslsigncode PRIVATE applink.c)
|
||||||
endif(WIN32)
|
endif(NOT UNIX)
|
||||||
|
|
||||||
# set include directories
|
# set include directories
|
||||||
target_include_directories(osslsigncode PRIVATE "${PROJECT_BINARY_DIR}")
|
target_include_directories(osslsigncode PRIVATE "${PROJECT_BINARY_DIR}")
|
||||||
@ -64,6 +66,7 @@ target_include_directories(osslsigncode PRIVATE ${OPENSSL_INCLUDE_DIR})
|
|||||||
target_link_libraries(osslsigncode PRIVATE ${OPENSSL_LIBRARIES})
|
target_link_libraries(osslsigncode PRIVATE ${OPENSSL_LIBRARIES})
|
||||||
|
|
||||||
# set cURL includes/libraries
|
# set cURL includes/libraries
|
||||||
|
if(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
if(CURL_FOUND)
|
if(CURL_FOUND)
|
||||||
target_compile_definitions(osslsigncode PRIVATE ENABLE_CURL=1)
|
target_compile_definitions(osslsigncode PRIVATE ENABLE_CURL=1)
|
||||||
target_include_directories(osslsigncode PRIVATE ${CURL_INCLUDE_DIRS})
|
target_include_directories(osslsigncode PRIVATE ${CURL_INCLUDE_DIRS})
|
||||||
@ -72,6 +75,18 @@ if(CURL_FOUND)
|
|||||||
else(CURL_FOUND)
|
else(CURL_FOUND)
|
||||||
message(STATUS "cURL support disabled (library not found)")
|
message(STATUS "cURL support disabled (library not found)")
|
||||||
endif(CURL_FOUND)
|
endif(CURL_FOUND)
|
||||||
|
endif(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
|
|
||||||
|
if(NOT ZLIB_FOUND)
|
||||||
|
message(FATAL_ERROR "Zlib library not found")
|
||||||
|
endif(NOT ZLIB_FOUND)
|
||||||
|
target_include_directories(osslsigncode PRIVATE ${ZLIB_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osslsigncode PRIVATE ${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
|
if(NOT UNIX)
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-shutdown
|
||||||
|
target_link_libraries(osslsigncode PRIVATE Ws2_32.lib crypt32.lib)
|
||||||
|
endif(NOT UNIX)
|
||||||
|
|
||||||
# add paths to linker search and installed rpath
|
# add paths to linker search and installed rpath
|
||||||
set_target_properties(osslsigncode PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
set_target_properties(osslsigncode PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
@ -80,16 +95,25 @@ set_target_properties(osslsigncode PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|||||||
include(CMakeTest)
|
include(CMakeTest)
|
||||||
|
|
||||||
# installation rules for a project
|
# installation rules for a project
|
||||||
install(TARGETS osslsigncode RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
if(WIN32)
|
install(TARGETS osslsigncode RUNTIME DESTINATION ${BINDIR})
|
||||||
|
if(UNIX)
|
||||||
|
include(CMakeDist)
|
||||||
|
else(UNIX)
|
||||||
install(
|
install(
|
||||||
DIRECTORY ${PROJECT_BINARY_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}
|
DIRECTORY ${PROJECT_BINARY_DIR}/ DESTINATION ${BINDIR}
|
||||||
FILES_MATCHING
|
FILES_MATCHING
|
||||||
PATTERN "*.dll"
|
PATTERN "*.dll"
|
||||||
PATTERN "vcpkg_installed" EXCLUDE
|
PATTERN "vcpkg_installed" EXCLUDE
|
||||||
PATTERN "CMakeFiles" EXCLUDE
|
PATTERN "CMakeFiles" EXCLUDE
|
||||||
PATTERN "Testing" EXCLUDE
|
PATTERN "Testing" EXCLUDE)
|
||||||
)
|
endif(UNIX)
|
||||||
else(WIN32)
|
|
||||||
include(CMakeDist)
|
#[[
|
||||||
endif(WIN32)
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
@ -3,10 +3,8 @@
|
|||||||
#define VERSION_MINOR "@osslsigncode_VERSION_MINOR@"
|
#define VERSION_MINOR "@osslsigncode_VERSION_MINOR@"
|
||||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||||
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
||||||
#cmakedefine ENABLE_CURL
|
|
||||||
#cmakedefine HAVE_TERMIOS_H
|
#cmakedefine HAVE_TERMIOS_H
|
||||||
#cmakedefine HAVE_GETPASS
|
#cmakedefine HAVE_GETPASS
|
||||||
#cmakedefine HAVE_SYS_MMAN_H
|
#cmakedefine HAVE_SYS_MMAN_H
|
||||||
#cmakedefine HAVE_MMAP
|
#cmakedefine HAVE_MMAP
|
||||||
#cmakedefine HAVE_MAPVIEWOFFILE
|
#cmakedefine HAVE_MAPVIEWOFFILE
|
||||||
#cmakedefine _WIN32
|
|
||||||
|
32
Dockerfile
Normal file
32
Dockerfile
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Stage 1: Build osslsigncode on Alpine
|
||||||
|
FROM alpine:latest AS builder
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apk add --no-cache build-base cmake openssl-dev zlib-dev
|
||||||
|
|
||||||
|
# Copy osslsigncode source code into the image
|
||||||
|
COPY . /source
|
||||||
|
|
||||||
|
# Build osslsigncode
|
||||||
|
RUN cd /source && \
|
||||||
|
mkdir -p build && \
|
||||||
|
cd build && \
|
||||||
|
rm -f CMakeCache.txt && \
|
||||||
|
cmake -S .. && \
|
||||||
|
cmake --build . && \
|
||||||
|
cmake --install .
|
||||||
|
|
||||||
|
# Stage 2: Create final image without build environment
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# Copy compiled binary from builder stage
|
||||||
|
COPY --from=builder /usr/local/bin/osslsigncode /usr/local/bin/osslsigncode
|
||||||
|
|
||||||
|
# Install necessary runtime libraries (latest version)
|
||||||
|
RUN apk add --no-cache libcrypto3
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /workdir
|
||||||
|
|
||||||
|
# Declare volume to mount files
|
||||||
|
VOLUME [ "/workdir" ]
|
@ -3,50 +3,40 @@
|
|||||||
### Building osslsigncode source with MSYS2 MinGW 64-bit and MSYS2 packages:
|
### Building osslsigncode source with MSYS2 MinGW 64-bit and MSYS2 packages:
|
||||||
|
|
||||||
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
||||||
Once up and running install even mingw-w64-x86_64-gcc, mingw-w64-x86_64-curl.
|
Once up and running install the following packages:
|
||||||
```
|
```
|
||||||
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-curl
|
pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-openssl mingw-w64-x86_64-python-cryptography
|
||||||
```
|
```
|
||||||
mingw-w64-x86_64-openssl and mingw-w64-x86_64-zlib packages are installed with dependencies.
|
mingw-w64-x86_64-zlib package is installed with dependencies.
|
||||||
|
|
||||||
2) Run "MSYS2 MinGW 64-bit" and build 64-bit Windows executables.
|
2) Run "MSYS2 MinGW 64-bit" and build 64-bit Windows executables.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
cd osslsigncode-folder
|
||||||
x86_64-w64-mingw32-gcc osslsigncode.c msi.c -o osslsigncode.exe \
|
mkdir build && cd build && cmake -S .. -DCMAKE_BUILD_TYPE=Release -G "MSYS Makefiles"
|
||||||
-lcrypto -lssl -lcurl \
|
cmake --build . --verbose
|
||||||
-D 'PACKAGE_STRING="osslsigncode x.y"' \
|
|
||||||
-D 'PACKAGE_BUGREPORT="Your.Email@example.com"' \
|
|
||||||
-D ENABLE_CURL
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3) Run "Command prompt" and include "c:\msys64\mingw64\bin" folder as part of the path.
|
3) Make tests.
|
||||||
|
```
|
||||||
|
ctest
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Run "Command prompt" and include "c:\msys64\mingw64\bin" folder as part of the path.
|
||||||
```
|
```
|
||||||
path=%path%;c:\msys64\mingw64\bin
|
path=%path%;c:\msys64\mingw64\bin
|
||||||
cd osslsigncode-folder
|
|
||||||
osslsigncode.exe -v
|
osslsigncode.exe -v
|
||||||
osslsigncode 2.4, using:
|
osslsigncode 2.8, using:
|
||||||
OpenSSL 1.1.1g 21 Apr 2020 (Library: OpenSSL 1.1.1g 21 Apr 2020)
|
OpenSSL 3.2.0 23 Nov 2023 (Library: OpenSSL 3.2.0 23 Nov 2023)
|
||||||
libcurl/7.70.0 OpenSSL/1.1.1g (Schannel) zlib/1.2.11 brotli/1.0.7 libidn2/2.3.0
|
No default -CAfile location detected
|
||||||
libpsl/0.21.0 (+libidn2/2.3.0) libssh2/1.9.0 nghttp2/1.40.0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Building OpenSSL and osslsigncode sources with MSYS2 MinGW 64-bit:
|
||||||
### Building OpenSSL, Curl and osslsigncode sources with MSYS2 MinGW 64-bit:
|
|
||||||
|
|
||||||
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
||||||
Once up and running install even: perl make autoconf automake libtool pkg-config.
|
Once up and running install even: perl make autoconf automake libtool pkg-config.
|
||||||
```
|
```
|
||||||
pacman -S perl make autoconf automake libtool pkg-config
|
pacman -S perl make autoconf automake libtool pkg-config
|
||||||
```
|
```
|
||||||
Make sure there are no curl, brotli, libpsl, libidn2 and nghttp2 packages installed:
|
|
||||||
```
|
|
||||||
pacman -R mingw-w64-x86_64-curl \
|
|
||||||
mingw-w64-x86_64-brotli \
|
|
||||||
mingw-w64-x86_64-libpsl \
|
|
||||||
mingw-w64-x86_64-libidn2 \
|
|
||||||
mingw-w64-x86_64-nghttp2
|
|
||||||
```
|
|
||||||
|
|
||||||
Run "MSYS2 MinGW 64-bit" in the administrator mode.
|
Run "MSYS2 MinGW 64-bit" in the administrator mode.
|
||||||
|
|
||||||
2) Build and install OpenSSL.
|
2) Build and install OpenSSL.
|
||||||
@ -55,46 +45,30 @@
|
|||||||
./config --prefix='C:/OpenSSL' --openssldir='C:/OpenSSL'
|
./config --prefix='C:/OpenSSL' --openssldir='C:/OpenSSL'
|
||||||
make && make install
|
make && make install
|
||||||
```
|
```
|
||||||
3) Build and install curl.
|
|
||||||
```
|
|
||||||
cd curl-(version)
|
|
||||||
./buildconf
|
|
||||||
./configure --prefix='C:/curl' --with-ssl='C:/OpenSSL' \
|
|
||||||
--disable-ftp --disable-tftp --disable-file --disable-dict \
|
|
||||||
--disable-telnet --disable-imap --disable-smb --disable-smtp \
|
|
||||||
--disable-gopher --disable-pop --disable-pop3 --disable-rtsp \
|
|
||||||
--disable-ldap --disable-ldaps --disable-unix-sockets \
|
|
||||||
--disable-pthreads --without-zstd --without-zlib
|
|
||||||
make && make install
|
|
||||||
```
|
|
||||||
|
|
||||||
3) Build 64-bit Windows executables.
|
3) Configure a CMake project.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
mkdir build && cd build && cmake -S .. -DCMAKE_BUILD_TYPE=Release -G "MSYS Makefiles" -DCMAKE_PREFIX_PATH="C:\OpenSSL"
|
||||||
x86_64-w64-mingw32-gcc osslsigncode.c msi.c -o osslsigncode.exe \
|
|
||||||
-L 'C:/OpenSSL/lib/' -lcrypto -lssl \
|
|
||||||
-I 'C:/OpenSSL/include/' \
|
|
||||||
-L 'C:/curl/lib' -lcurl \
|
|
||||||
-I 'C:/curl/include' \
|
|
||||||
-D 'PACKAGE_STRING="osslsigncode x.y"' \
|
|
||||||
-D 'PACKAGE_BUGREPORT="Your.Email@example.com"' \
|
|
||||||
-D ENABLE_CURL
|
|
||||||
```
|
```
|
||||||
|
|
||||||
4) Run "Command prompt" and copy required libraries.
|
4) Run "Command prompt" and copy required libraries.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
cd osslsigncode-folder
|
||||||
copy C:\OpenSSL\bin\libssl-1_1-x64.dll
|
copy C:\OpenSSL\bin\libssl-3-x64.dll
|
||||||
copy C:\OpenSSL\bin\libcrypto-1_1-x64.dll
|
copy C:\OpenSSL\bin\libcrypto-3-x64.dll
|
||||||
copy C:\curl\bin\libcurl-4.dll
|
|
||||||
|
|
||||||
osslsigncode.exe -v
|
|
||||||
osslsigncode 2.4, using:
|
|
||||||
OpenSSL 1.1.1k 25 Mar 2021 (Library: OpenSSL 1.1.1k 25 Mar 2021)
|
|
||||||
libcurl/7.78.0 OpenSSL/1.1.1k
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building OpenSSL, Curl and osslsigncode sources with Microsoft Visual Studio:
|
5) Build 64-bit Windows executables.
|
||||||
|
```
|
||||||
|
cmake --build . --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
6) Make tests.
|
||||||
|
```
|
||||||
|
ctest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building OpenSSL and osslsigncode sources with Microsoft Visual Studio:
|
||||||
|
|
||||||
1) Install and integrate vcpkg: https://vcpkg.io/en/getting-started.html
|
1) Install and integrate vcpkg: https://vcpkg.io/en/getting-started.html
|
||||||
|
|
||||||
|
63
NEWS.md
63
NEWS.md
@ -1,5 +1,68 @@
|
|||||||
# osslsigncode change log
|
# osslsigncode change log
|
||||||
|
|
||||||
|
### 2.9 (2024.06.29)
|
||||||
|
|
||||||
|
- added a 64 bit long pseudo-random NONCE in the TSA request
|
||||||
|
- missing NID_pkcs9_signingTime is no longer an error
|
||||||
|
- added support for PEM-encoded CRLs
|
||||||
|
- fixed the APPX central directory sorting order
|
||||||
|
- added a special "-" file name to read the passphrase from stdin
|
||||||
|
(by Steve McIntyre)
|
||||||
|
- used native HTTP client with OpenSSL 3.x, removing libcurl dependency
|
||||||
|
- added '-login' option to force a login to PKCS11 engines
|
||||||
|
(by Brad Hughes)
|
||||||
|
- added the "-ignore-crl" option to disable fetching and verifying
|
||||||
|
CRL Distribution Points
|
||||||
|
- changed error output to stderr instead of stdout
|
||||||
|
- various testing framework improvements
|
||||||
|
- various memory corruption fixes
|
||||||
|
|
||||||
|
### 2.8 (2024.03.03)
|
||||||
|
|
||||||
|
- Microsoft PowerShell signing sponsored by Cisco Systems, Inc.
|
||||||
|
- fixed setting unauthenticated attributes (Countersignature, Unauthenticated
|
||||||
|
Data Blob) in a nested signature
|
||||||
|
- added the "-index" option to verify a specific signature or modify its
|
||||||
|
unauthenticated attributes
|
||||||
|
- added CAT file verification
|
||||||
|
- added listing the contents of a CAT file with the "-verbose" option
|
||||||
|
- added the new "extract-data" command to extract a PKCS#7 data content to be
|
||||||
|
signed with "sign" and attached with "attach-signature"
|
||||||
|
- added PKCS9_SEQUENCE_NUMBER authenticated attribute support
|
||||||
|
- added the "-ignore-cdp" option to disable CRL Distribution Points (CDP)
|
||||||
|
online verification
|
||||||
|
- unsuccessful CRL retrieval and verification changed into a critical error
|
||||||
|
- the "-p" option modified to also use to configured proxy to connect CRL
|
||||||
|
Distribution Points
|
||||||
|
- added implicit allowlisting of the Microsoft Root Authority serial number
|
||||||
|
00C1008B3C3C8811D13EF663ECDF40
|
||||||
|
- added listing of certificate chain retrieved from the signature in case of
|
||||||
|
verification failure
|
||||||
|
|
||||||
|
### 2.7 (2023.09.19)
|
||||||
|
|
||||||
|
- fixed signing CAB files (by Michael Brown)
|
||||||
|
- fixed handling of unsupported commands (by Maxim Bagryantsev)
|
||||||
|
- fixed writing DIFAT sectors
|
||||||
|
- added APPX support (by Maciej Panek and Małgorzata Olszówka)
|
||||||
|
- added a built-in TSA response generation (-TSA-certs, -TSA-key
|
||||||
|
and -TSA-time options)
|
||||||
|
|
||||||
|
### 2.6 (2023.05.29)
|
||||||
|
|
||||||
|
- modular architecture implemented to simplify adding file formats
|
||||||
|
- added verification of CRLs specified in the signing certificate
|
||||||
|
- added MSI DIFAT sectors support (by Max Bagryantsev)
|
||||||
|
- added legacy provider support for OpenSSL 3.0.0 and later
|
||||||
|
- fixed numerous bugs
|
||||||
|
|
||||||
|
### 2.5 (2022.08.12)
|
||||||
|
|
||||||
|
- fixed the Unix executable install path
|
||||||
|
- fixed the hardcoded "pkcs11" engine id
|
||||||
|
- fixed building with MinGW
|
||||||
|
- fixed testing with the python3 distributed with Ubuntu 18.04
|
||||||
|
|
||||||
### 2.4 (2022.08.02)
|
### 2.4 (2022.08.02)
|
||||||
|
|
||||||
- migrated the build system from GNU Autoconf to CMake
|
- migrated the build system from GNU Autoconf to CMake
|
||||||
|
22
README.md
22
README.md
@ -39,25 +39,29 @@ We highly recommend downloading a [release tarball](https://github.com/mtrojnar/
|
|||||||
|
|
||||||
* Install prerequisites on a Debian-based distributions, such as Ubuntu:
|
* Install prerequisites on a Debian-based distributions, such as Ubuntu:
|
||||||
```
|
```
|
||||||
sudo apt update && sudo apt install cmake libssl-dev libcurl4-openssl-dev
|
sudo apt update && sudo apt install cmake libssl-dev libcurl4-openssl-dev zlib1g-dev python3
|
||||||
```
|
```
|
||||||
* Install prerequisites on macOS with Homebrew:
|
* Install prerequisites on macOS with Homebrew:
|
||||||
```
|
```
|
||||||
brew install cmake pkg-config openssl@1.1
|
brew install cmake pkg-config openssl@1.1
|
||||||
export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"
|
export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"
|
||||||
```
|
```
|
||||||
**NOTE:** osslsigncode requires CMake 3.6 or newer.
|
**NOTE:** osslsigncode requires CMake 3.17 or newer.
|
||||||
|
|
||||||
You may need to use `cmake3` instead of `cmake` to complete the following steps on your system.
|
You may need to use `cmake3` instead of `cmake` to complete the following steps on your system.
|
||||||
* Navigate to the build directory and run CMake to configure the osslsigncode project
|
* Navigate to the build directory and run CMake to configure the osslsigncode project
|
||||||
and generate a native build system:
|
and generate a native build system:
|
||||||
```
|
```
|
||||||
mkdir build && cd build && cmake ..
|
mkdir build && cd build && cmake -S ..
|
||||||
```
|
```
|
||||||
with specific compile options:
|
optional CMake parameters:
|
||||||
```
|
```
|
||||||
-Denable-strict=ON
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
-Denable-pedantic=ON
|
-DCMAKE_C_COMPILER=clang
|
||||||
|
-DCMAKE_PREFIX_PATH=[openssl directory];[curl directory]
|
||||||
|
-DCMAKE_INSTALL_PREFIX=[installation directory]
|
||||||
|
-DBASH_COMPLETION_USER_DIR=[bash completion installation directory]
|
||||||
|
|
||||||
```
|
```
|
||||||
* Then call that build system to actually compile/link the osslsigncode project (alias `make`):
|
* Then call that build system to actually compile/link the osslsigncode project (alias `make`):
|
||||||
```
|
```
|
||||||
@ -69,7 +73,7 @@ You may need to use `cmake3` instead of `cmake` to complete the following steps
|
|||||||
```
|
```
|
||||||
* Make install:
|
* Make install:
|
||||||
```
|
```
|
||||||
sudo cmake --install . --prefix "/home/myuser/installdir"
|
sudo cmake --install .
|
||||||
```
|
```
|
||||||
* Make tarball (simulate autotools' `make dist`):
|
* Make tarball (simulate autotools' `make dist`):
|
||||||
```
|
```
|
||||||
@ -177,9 +181,7 @@ in the unauthenticated blob, as an attacker could modify this. Do NOT, under
|
|||||||
any circumstances, put a URL here that you will use to download an additional
|
any circumstances, put a URL here that you will use to download an additional
|
||||||
file. If you do do that, you would need to check the newly downloaded file is
|
file. If you do do that, you would need to check the newly downloaded file is
|
||||||
code signed AND that it has been signed with your cert AND that it is the
|
code signed AND that it has been signed with your cert AND that it is the
|
||||||
version you expect. You should consider using asymmetrical encryption for the
|
version you expect.
|
||||||
data you put in the blob, such that the executable contains the public key to
|
|
||||||
decrypt the data. Basically, be VERY careful.
|
|
||||||
|
|
||||||
## BUGS, QUESTIONS etc.
|
## BUGS, QUESTIONS etc.
|
||||||
|
|
||||||
|
490
cat.c
Normal file
490
cat.c
Normal file
@ -0,0 +1,490 @@
|
|||||||
|
/*
|
||||||
|
* CAT file support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*
|
||||||
|
* Catalog files are a bit odd, in that they are only a PKCS7 blob.
|
||||||
|
* CAT files do not support nesting (multiple signature)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osslsigncode.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_BMPSTRING *tag;
|
||||||
|
ASN1_INTEGER *flags;
|
||||||
|
ASN1_OCTET_STRING *value;
|
||||||
|
} CatNameValueContent;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(CatNameValueContent)
|
||||||
|
|
||||||
|
ASN1_SEQUENCE(CatNameValueContent) = {
|
||||||
|
ASN1_SIMPLE(CatNameValueContent, tag, ASN1_BMPSTRING),
|
||||||
|
ASN1_SIMPLE(CatNameValueContent, flags, ASN1_INTEGER),
|
||||||
|
ASN1_SIMPLE(CatNameValueContent, value, ASN1_OCTET_STRING)
|
||||||
|
} ASN1_SEQUENCE_END(CatNameValueContent)
|
||||||
|
|
||||||
|
IMPLEMENT_ASN1_FUNCTIONS(CatNameValueContent)
|
||||||
|
|
||||||
|
struct cat_ctx_st {
|
||||||
|
uint32_t sigpos;
|
||||||
|
uint32_t siglen;
|
||||||
|
uint32_t fileend;
|
||||||
|
PKCS7 *p7;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FILE_FORMAT method prototypes */
|
||||||
|
static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
|
static int cat_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
|
static PKCS7 *cat_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *cat_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
|
static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
static void cat_bio_free(BIO *hash, BIO *outdata);
|
||||||
|
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
FILE_FORMAT file_format_cat = {
|
||||||
|
.ctx_new = cat_ctx_new,
|
||||||
|
.verify_digests = cat_verify_digests,
|
||||||
|
.pkcs7_extract = cat_pkcs7_extract,
|
||||||
|
.pkcs7_signature_new = cat_pkcs7_signature_new,
|
||||||
|
.append_pkcs7 = cat_append_pkcs7,
|
||||||
|
.bio_free = cat_bio_free,
|
||||||
|
.ctx_cleanup = cat_ctx_cleanup,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize);
|
||||||
|
static int cat_add_ms_ctl_object(PKCS7 *p7);
|
||||||
|
static int cat_sign_ms_ctl_content(PKCS7 *p7, PKCS7 *contents);
|
||||||
|
static int cat_list_content(PKCS7 *p7);
|
||||||
|
static int cat_print_content_member_digest(ASN1_TYPE *content);
|
||||||
|
static int cat_print_content_member_name(ASN1_TYPE *content);
|
||||||
|
static void cat_print_base64(ASN1_OCTET_STRING *value);
|
||||||
|
static void cat_print_utf16_as_ascii(ASN1_OCTET_STRING *value);
|
||||||
|
static int cat_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FILE_FORMAT method definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return a CAT file format context.
|
||||||
|
* [in, out] options: structure holds the input data
|
||||||
|
* [out] hash: message digest BIO (unused)
|
||||||
|
* [in] outdata: outdata file BIO (unused)
|
||||||
|
* [returns] pointer to CAT file format context
|
||||||
|
*/
|
||||||
|
static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
FILE_FORMAT_CTX *ctx;
|
||||||
|
CAT_CTX *cat_ctx;
|
||||||
|
uint32_t filesize;
|
||||||
|
|
||||||
|
if (options->cmd == CMD_REMOVE || options->cmd==CMD_ATTACH || options->cmd == CMD_EXTRACT_DATA) {
|
||||||
|
fprintf(stderr, "Unsupported command\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
filesize = get_file_size(options->infile);
|
||||||
|
if (filesize == 0)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
|
||||||
|
options->indata = map_file(options->infile, filesize);
|
||||||
|
if (!options->indata) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
cat_ctx = cat_ctx_get(options->indata, filesize);
|
||||||
|
if (!cat_ctx) {
|
||||||
|
unmap_file(options->indata, filesize);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
|
ctx->format = &file_format_cat;
|
||||||
|
ctx->options = options;
|
||||||
|
ctx->cat_ctx = cat_ctx;
|
||||||
|
|
||||||
|
/* Push hash on outdata, if hash is NULL the function does nothing */
|
||||||
|
BIO_push(hash, outdata);
|
||||||
|
|
||||||
|
if (options->cmd == CMD_VERIFY)
|
||||||
|
printf("Warning: Use -catalog option to verify that a file, listed in catalog file, is signed\n");
|
||||||
|
if (options->jp >= 0)
|
||||||
|
printf("Warning: -jp option is only valid for CAB files\n");
|
||||||
|
if (options->pagehash == 1)
|
||||||
|
printf("Warning: -ph option is only valid for PE files\n");
|
||||||
|
if (options->add_msi_dse == 1)
|
||||||
|
printf("Warning: -add-msi-dse option is only valid for MSI files\n");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ContentInfo value is the inner content of pkcs7-signedData.
|
||||||
|
* An extra verification is not necessary when a content type data
|
||||||
|
* is the inner content of the signed-data type.
|
||||||
|
*/
|
||||||
|
static int cat_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
/* squash unused parameter warnings */
|
||||||
|
(void)ctx;
|
||||||
|
(void)p7;
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *cat_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (!cat_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return PKCS7_dup(ctx->cat_ctx->p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new PKCS#7 signature.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO (unused)
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *cat_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
PKCS7 *p7 = NULL;
|
||||||
|
|
||||||
|
/* squash unused parameter warnings */
|
||||||
|
(void)hash;
|
||||||
|
|
||||||
|
p7 = pkcs7_create(ctx);
|
||||||
|
if (!p7) {
|
||||||
|
fprintf(stderr, "Creating a new signature failed\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!cat_add_ms_ctl_object(p7)) {
|
||||||
|
fprintf(stderr, "Adding MS_CTL_OBJID failed\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!ctx->cat_ctx->p7 || !ctx->cat_ctx->p7->d.sign || !ctx->cat_ctx->p7->d.sign->contents) {
|
||||||
|
fprintf(stderr, "Failed to get content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!cat_sign_ms_ctl_content(p7, ctx->cat_ctx->p7->d.sign->contents)) {
|
||||||
|
fprintf(stderr, "Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return p7; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append signature to the outfile.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
return data_write_pkcs7(ctx, outdata, p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free up an entire message digest BIO chain.
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO (unused)
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_bio_free(BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)outdata;
|
||||||
|
BIO_free_all(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate a FILE_FORMAT_CTX structure and CAT format specific structure,
|
||||||
|
* unmap indata file.
|
||||||
|
* [in, out] ctx: structure holds all input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [in] outdata: outdata file BIO
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
unmap_file(ctx->options->indata, ctx->cat_ctx->fileend);
|
||||||
|
PKCS7_free(ctx->cat_ctx->p7);
|
||||||
|
OPENSSL_free(ctx->cat_ctx);
|
||||||
|
OPENSSL_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAT helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify mapped PKCS#7 (CAT) file and create CAT format specific structure.
|
||||||
|
* [in] indata: mapped file
|
||||||
|
* [in] filesize: size of file
|
||||||
|
* [returns] pointer to CAT format specific structure
|
||||||
|
*/
|
||||||
|
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize)
|
||||||
|
{
|
||||||
|
CAT_CTX *cat_ctx;
|
||||||
|
PKCS7 *p7;
|
||||||
|
|
||||||
|
p7 = pkcs7_read_data(indata, filesize);
|
||||||
|
if (!p7)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
if (!PKCS7_type_is_signed(p7)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
cat_ctx = OPENSSL_zalloc(sizeof(CAT_CTX));
|
||||||
|
cat_ctx->p7 = p7;
|
||||||
|
cat_ctx->sigpos = 0;
|
||||||
|
cat_ctx->siglen = filesize;
|
||||||
|
cat_ctx->fileend = filesize;
|
||||||
|
return cat_ctx; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add "1.3.6.1.4.1.311.10.1" MS_CTL_OBJID signed attribute
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_add_ms_ctl_object(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
|
PKCS7_SIGNER_INFO *si;
|
||||||
|
|
||||||
|
signer_info = PKCS7_get_signer_info(p7);
|
||||||
|
if (!signer_info)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
|
||||||
|
V_ASN1_OBJECT, OBJ_txt2obj(MS_CTL_OBJID, 1)))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sign the MS CTL blob.
|
||||||
|
* Certificate Trust List (CTL) is a list of file names or thumbprints.
|
||||||
|
* All the items in this list are authenticated (approved) by the signing entity.
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] contents: Certificate Trust List (CTL)
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_sign_ms_ctl_content(PKCS7 *p7, PKCS7 *contents)
|
||||||
|
{
|
||||||
|
u_char *content;
|
||||||
|
int seqhdrlen, content_length;
|
||||||
|
|
||||||
|
if (!contents->d.other || !contents->d.other->value.sequence
|
||||||
|
|| !contents->d.other->value.sequence->data) {
|
||||||
|
fprintf(stderr, "Failed to get content value\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
seqhdrlen = asn1_simple_hdr_len(contents->d.other->value.sequence->data,
|
||||||
|
contents->d.other->value.sequence->length);
|
||||||
|
content = contents->d.other->value.sequence->data + seqhdrlen;
|
||||||
|
content_length = contents->d.other->value.sequence->length - seqhdrlen;
|
||||||
|
|
||||||
|
if (!pkcs7_sign_content(p7, content, content_length)) {
|
||||||
|
fprintf(stderr, "Failed to sign content\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!PKCS7_set_content(p7, PKCS7_dup(contents))) {
|
||||||
|
fprintf(stderr, "PKCS7_set_content failed\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print each member of the CAT file by using the "-verbose" option.
|
||||||
|
* [in, out] p7: catalog file to verify
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int cat_list_content(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
MsCtlContent *ctlc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ctlc = ms_ctl_content_get(p7);
|
||||||
|
if (!ctlc) {
|
||||||
|
fprintf(stderr, "Failed to extract MS_CTL_OBJID data\n");
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
printf("\nCatalog members:\n");
|
||||||
|
for (i = 0; i < sk_CatalogInfo_num(ctlc->header_attributes); i++) {
|
||||||
|
int j, found = 0;
|
||||||
|
CatalogInfo *header_attr = sk_CatalogInfo_value(ctlc->header_attributes, i);
|
||||||
|
if (header_attr == NULL)
|
||||||
|
continue;
|
||||||
|
for (j = 0; j < sk_CatalogAuthAttr_num(header_attr->attributes); j++) {
|
||||||
|
char object_txt[128];
|
||||||
|
CatalogAuthAttr *attribute;
|
||||||
|
ASN1_TYPE *content;
|
||||||
|
|
||||||
|
attribute = sk_CatalogAuthAttr_value(header_attr->attributes, j);
|
||||||
|
if (!attribute)
|
||||||
|
continue;
|
||||||
|
content = catalog_content_get(attribute);
|
||||||
|
if (!content)
|
||||||
|
continue;
|
||||||
|
object_txt[0] = 0x00;
|
||||||
|
OBJ_obj2txt(object_txt, sizeof object_txt, attribute->type, 1);
|
||||||
|
if (!strcmp(object_txt, CAT_NAMEVALUE_OBJID)) {
|
||||||
|
/* CAT_NAMEVALUE_OBJID OID: 1.3.6.1.4.1.311.12.2.1 */
|
||||||
|
found |= cat_print_content_member_name(content);
|
||||||
|
} else if (!strcmp(object_txt, SPC_INDIRECT_DATA_OBJID)) {
|
||||||
|
/* SPC_INDIRECT_DATA_OBJID OID: 1.3.6.1.4.1.311.2.1.4 */
|
||||||
|
found |= cat_print_content_member_digest(content);
|
||||||
|
}
|
||||||
|
ASN1_TYPE_free(content);
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
MsCtlContent_free(ctlc);
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
return 0; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a hash algorithm and a message digest from the SPC_INDIRECT_DATA_OBJID attribute.
|
||||||
|
* [in] content: catalog file content
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_print_content_member_digest(ASN1_TYPE *content)
|
||||||
|
{
|
||||||
|
SpcIndirectDataContent *idc;
|
||||||
|
u_char mdbuf[EVP_MAX_MD_SIZE];
|
||||||
|
const u_char *data ;
|
||||||
|
int mdtype = -1;
|
||||||
|
ASN1_STRING *value;
|
||||||
|
|
||||||
|
value = content->value.sequence;
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
idc = d2i_SpcIndirectDataContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
|
if (!idc)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||||
|
/* get a digest algorithm a message digest of the file from the content */
|
||||||
|
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||||
|
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||||
|
}
|
||||||
|
SpcIndirectDataContent_free(idc);
|
||||||
|
if (mdtype == -1) {
|
||||||
|
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
printf("\tHash algorithm: %s\n", OBJ_nid2sn(mdtype));
|
||||||
|
print_hash("\tMessage digest", "", mdbuf, EVP_MD_size(EVP_get_digestbynid(mdtype)));
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a file name from the CAT_NAMEVALUE_OBJID attribute.
|
||||||
|
* [in] content: catalog file content
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_print_content_member_name(ASN1_TYPE *content)
|
||||||
|
{
|
||||||
|
CatNameValueContent *nvc;
|
||||||
|
const u_char *data = NULL;
|
||||||
|
ASN1_STRING *value;
|
||||||
|
|
||||||
|
value = content->value.sequence;
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
nvc = d2i_CatNameValueContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
|
if (!nvc) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
printf("\tFile name: ");
|
||||||
|
if (ASN1_INTEGER_get(nvc->flags) & 0x00020000) {
|
||||||
|
cat_print_base64(nvc->value);
|
||||||
|
} else {
|
||||||
|
cat_print_utf16_as_ascii(nvc->value);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
CatNameValueContent_free(nvc);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a CAT_NAMEVALUE_OBJID attribute represented in base-64 encoding.
|
||||||
|
* [in] value: catalog member file name
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_print_base64(ASN1_OCTET_STRING *value)
|
||||||
|
{
|
||||||
|
BIO *stdbio, *b64;
|
||||||
|
stdbio = BIO_new_fp(stdout, BIO_NOCLOSE);
|
||||||
|
b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
stdbio = BIO_push(b64, stdbio);
|
||||||
|
ASN1_STRING_print_ex(stdbio, value, 0);
|
||||||
|
BIO_free_all(stdbio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a CAT_NAMEVALUE_OBJID attribute represented in plaintext.
|
||||||
|
* [in] value: catalog member file name
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_print_utf16_as_ascii(ASN1_OCTET_STRING *value)
|
||||||
|
{
|
||||||
|
const u_char *data;
|
||||||
|
int len, i;
|
||||||
|
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
len = ASN1_STRING_length(value);
|
||||||
|
for (i = 0; i < len && (data[i] || data[i+1]); i+=2)
|
||||||
|
putchar(isprint(data[i]) && !data[i+1] ? data[i] : '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the signature exists.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
|
PKCS7_SIGNER_INFO *si;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "Init error\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
signer_info = PKCS7_get_signer_info(ctx->cat_ctx->p7);
|
||||||
|
if (!signer_info) {
|
||||||
|
fprintf(stderr, "Failed catalog file\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si) {
|
||||||
|
fprintf(stderr, "No signature found\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->options->verbose) {
|
||||||
|
(void)cat_list_content(ctx->cat_ctx->p7);
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
@ -25,3 +25,12 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES "/build/")
|
|||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
|
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
@ -1,298 +1,624 @@
|
|||||||
# make test
|
# make test
|
||||||
# ctest -C Release
|
# ctest -C Release
|
||||||
|
|
||||||
include(FindPython3)
|
########## Configure ##########
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
set(FILES "${PROJECT_BINARY_DIR}/Testing/files")
|
include(FindPython3)
|
||||||
set(CERTS "${PROJECT_BINARY_DIR}/Testing/certs")
|
|
||||||
set(CONF "${PROJECT_BINARY_DIR}/Testing/conf")
|
if(Python3_FOUND)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} "check_cryptography.py"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
|
||||||
|
OUTPUT_VARIABLE cryptography_output
|
||||||
|
RESULT_VARIABLE cryptography_error)
|
||||||
|
|
||||||
|
if(NOT cryptography_error)
|
||||||
|
message(STATUS "Using python3-cryptography version ${cryptography_output}")
|
||||||
|
option(STOP_SERVER "Stop HTTP server after tests" ON)
|
||||||
|
|
||||||
|
# Remove http proxy configuration that may change behavior
|
||||||
|
unset(ENV{HTTP_PROXY})
|
||||||
|
unset(ENV{http_proxy})
|
||||||
|
|
||||||
|
set(TEST_DIR "${PROJECT_BINARY_DIR}/Testing")
|
||||||
|
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||||
|
set(OSSLSIGNCODE "${PROJECT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/osslsigncode")
|
||||||
|
else(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||||
|
set(OSSLSIGNCODE "${PROJECT_BINARY_DIR}/osslsigncode")
|
||||||
|
endif(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||||
|
set(EXEC "${TEST_DIR}/exec.py")
|
||||||
|
set(FILES "${TEST_DIR}/files")
|
||||||
|
set(CERTS "${TEST_DIR}/certs")
|
||||||
|
set(CONF "${TEST_DIR}/conf")
|
||||||
|
set(LOGS "${TEST_DIR}/logs")
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY "${LOGS}")
|
||||||
|
|
||||||
|
file(COPY
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/certs/ca-bundle.crt"
|
||||||
|
DESTINATION "${CONF}")
|
||||||
|
|
||||||
file(COPY
|
file(COPY
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/files"
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/files"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/conf"
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/conf"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/tsa_server.py"
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/client_http.py"
|
||||||
DESTINATION "${PROJECT_BINARY_DIR}/Testing"
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/make_certificates.py"
|
||||||
)
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/start_server.py"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/exec.py"
|
||||||
|
DESTINATION "${TEST_DIR}/")
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
file(COPY
|
file(COPY
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/certs/ca-bundle.crt"
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/server_http.py"
|
||||||
DESTINATION "${CONF}"
|
DESTINATION "${TEST_DIR}/")
|
||||||
)
|
set(SERVER_HTTP "${TEST_DIR}/server_http.py")
|
||||||
|
set(Python3w_EXECUTABLE ${Python3_EXECUTABLE})
|
||||||
|
else(UNIX)
|
||||||
|
file(COPY
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/server_http.pyw"
|
||||||
|
DESTINATION "${TEST_DIR}/")
|
||||||
|
set(SERVER_HTTP "${TEST_DIR}/server_http.pyw")
|
||||||
|
get_filename_component(PYTHON_DIRECTORY ${Python3_EXECUTABLE} DIRECTORY)
|
||||||
|
set(Python3w_EXECUTABLE "${PYTHON_DIRECTORY}/pythonw.exe")
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
set(priv_p12 "-pkcs12" "${CERTS}/cert.p12" "-readpass" "${CERTS}/password.txt")
|
if(EXISTS "${LOGS}/url.log")
|
||||||
set(priv_spc "-certs" "${CERTS}/cert.spc" "-key" "${CERTS}/key.pvk" "-pass" "passme")
|
# Stop HTTP server if running
|
||||||
set(priv_der "-certs" "${CERTS}/cert.pem" "-key" "${CERTS}/key.der" "-pass" "passme")
|
message(STATUS "Try to kill HTTP server")
|
||||||
set(priv_pkey "-certs" "${CERTS}/cert.pem" "-key" "${CERTS}/keyp.pem" "-pass" "passme")
|
execute_process(
|
||||||
set(sign_opt "-time" "1556708400"
|
COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/client_http.py"
|
||||||
"-add-msi-dse" "-comm" "-ph" "-jp" "low"
|
OUTPUT_VARIABLE client_output
|
||||||
|
RESULT_VARIABLE client_result)
|
||||||
|
if(NOT client_result)
|
||||||
|
# Successfully closed
|
||||||
|
message(STATUS "${client_output}")
|
||||||
|
endif(NOT client_result)
|
||||||
|
endif(EXISTS "${LOGS}/url.log")
|
||||||
|
|
||||||
|
set(extensions_all "exe" "ex_" "msi" "256appx" "512appx" "cat" "ps1" "psc1" "mof")
|
||||||
|
set(extensions_nocat "exe" "ex_" "msi" "256appx" "512appx" "ps1" "psc1" "mof")
|
||||||
|
set(extensions_nocatappx "exe" "ex_" "msi" "ps1" "psc1" "mof")
|
||||||
|
set(formats "pem" "der")
|
||||||
|
|
||||||
|
else(NOT cryptography_error)
|
||||||
|
message(STATUS "CTest skips tests: ${cryptography_output}")
|
||||||
|
endif(NOT cryptography_error)
|
||||||
|
|
||||||
|
else(Python3_FOUND)
|
||||||
|
message(STATUS "CTest skips tests: Python3 not found")
|
||||||
|
endif(Python3_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
########## Testing ##########
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
### osslsigncode version ###
|
||||||
|
if(Python3_FOUND AND NOT cryptography_error)
|
||||||
|
|
||||||
|
### Start ###
|
||||||
|
add_test(NAME "version"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE}
|
||||||
|
"--version")
|
||||||
|
|
||||||
|
add_test(NAME "start_server"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/start_server.py"
|
||||||
|
"--exe" ${Python3w_EXECUTABLE}
|
||||||
|
"--script" ${SERVER_HTTP})
|
||||||
|
set_tests_properties("start_server" PROPERTIES
|
||||||
|
TIMEOUT 60)
|
||||||
|
set(ALL_TESTS "version" "start_server")
|
||||||
|
|
||||||
|
### Sign ###
|
||||||
|
|
||||||
|
# Sign with PKCS#12 container with private key and certificate encryption algorithm
|
||||||
|
# Signing time: May 1 00:00:00 2019 GMT (1556668800)
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "signed_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
"-h" "sha512" "-i" "https://www.osslsigncode.com/"
|
"-h" "sha512" "-i" "https://www.osslsigncode.com/"
|
||||||
"-n" "osslsigncode" "-ac" "${CERTS}/crosscert.pem"
|
"-n" "osslsigncode"
|
||||||
)
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/signed.${ext}")
|
||||||
|
set_tests_properties("signed_${ext}" PROPERTIES
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "signed_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
if(NOT CMAKE_HOST_WIN32)
|
# Sign with revoked certificate
|
||||||
execute_process(
|
foreach(ext ${extensions_all})
|
||||||
COMMAND "${CONF}/makecerts.sh"
|
add_test(NAME "revoked_${ext}"
|
||||||
WORKING_DIRECTORY ${CONF}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
OUTPUT_VARIABLE makecerts_output
|
"-certs" "${CERTS}/revoked.pem"
|
||||||
RESULT_VARIABLE makecerts_result
|
"-key" "${CERTS}/keyp.pem"
|
||||||
)
|
"-readpass" "${CERTS}/password.txt"
|
||||||
else()
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
set(makecerts_result 1)
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
endif()
|
"-add-msi-dse"
|
||||||
if(makecerts_result)
|
"-comm"
|
||||||
message(STATUS "makecerts.sh failed")
|
"-ph"
|
||||||
if(makecerts_output)
|
"-jp" "low"
|
||||||
message(STATUS "${makecerts_output}")
|
"-h" "sha512" "-i" "https://www.osslsigncode.com/"
|
||||||
endif()
|
"-n" "osslsigncode"
|
||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests/certs"
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
DESTINATION "${PROJECT_BINARY_DIR}/Testing"
|
"-out" "${FILES}/revoked.${ext}")
|
||||||
)
|
set_tests_properties("revoked_${ext}" PROPERTIES
|
||||||
endif()
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "revoked_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
execute_process(
|
# Remove signature
|
||||||
COMMAND ${CMAKE_COMMAND} -E sha256sum "${CERTS}/cert.der"
|
# Unsupported command for CAT files
|
||||||
OUTPUT_VARIABLE sha256sum
|
foreach(ext ${extensions_nocat})
|
||||||
)
|
add_test(NAME "removed_${ext}"
|
||||||
string(SUBSTRING ${sha256sum} 0 64 leafhash)
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "remove-signature"
|
||||||
set(verify_opt "-CAfile" "${CERTS}/CACert.pem"
|
"-in" "${FILES}/signed.${ext}"
|
||||||
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
"-out" "${FILES}/removed.${ext}")
|
||||||
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
set_tests_properties("removed_${ext}" PROPERTIES
|
||||||
)
|
DEPENDS "signed_${ext}")
|
||||||
set(extensions_4 "exe" "ex_" "msi" "cat")
|
list(APPEND ALL_TESTS "removed_${ext}")
|
||||||
set(extensions_3 "exe" "ex_" "msi")
|
endforeach(ext ${extensions_nocat})
|
||||||
set(files_4 "signed" "nested" "added")
|
|
||||||
set(files_3 "removed" "attached_pem" "attached_der")
|
|
||||||
set(sign_formats "pem" "der")
|
|
||||||
set(pem_certs "cert" "expired" "revoked")
|
|
||||||
set(failed_certs "expired" "revoked")
|
|
||||||
|
|
||||||
add_test(
|
# Extract PKCS#7 signature in PEM format
|
||||||
NAME version
|
foreach(ext ${extensions_all})
|
||||||
COMMAND osslsigncode --version
|
add_test(NAME "extract_pem_${ext}"
|
||||||
)
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-signature"
|
||||||
|
"-pem" # PEM format
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/${ext}.pem")
|
||||||
|
set_tests_properties("extract_pem_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "extract_pem_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
# Extract PKCS#7 signature in default DER format
|
||||||
# Signing time: May 1 00:00:00 2019 GMT
|
foreach(ext ${extensions_all})
|
||||||
set(sign_${ext} )
|
add_test(NAME "extract_der_${ext}"
|
||||||
add_test(
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-signature"
|
||||||
NAME signed_${ext}
|
"-in" "${FILES}/signed.${ext}"
|
||||||
COMMAND osslsigncode "sign" ${sign_opt} ${priv_p12}
|
"-out" "${FILES}/${ext}.der")
|
||||||
"-in" "${FILES}/unsigned.${ext}" "-out" "${FILES}/signed.${ext}"
|
set_tests_properties("extract_der_${ext}" PROPERTIES
|
||||||
)
|
DEPENDS "signed_${ext}")
|
||||||
endforeach()
|
list(APPEND ALL_TESTS "extract_der_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
# Attach a nested signature in PEM or DER format
|
||||||
add_test(
|
# Unsupported command for CAT files
|
||||||
NAME removed_${ext}
|
foreach(ext ${extensions_nocat})
|
||||||
COMMAND osslsigncode "remove-signature"
|
foreach(format ${formats})
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/removed.${ext}"
|
add_test(NAME "attached_${format}_${ext}"
|
||||||
)
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "attach-signature"
|
||||||
endforeach()
|
# sign options
|
||||||
|
"-add-msi-dse"
|
||||||
foreach(ext ${extensions_3})
|
"-h" "sha512"
|
||||||
add_test(
|
"-nest"
|
||||||
NAME extract_pem_${ext}
|
|
||||||
COMMAND osslsigncode "extract-signature" "-pem"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/${ext}.pem"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
add_test(
|
|
||||||
NAME extract_der_${ext}
|
|
||||||
COMMAND osslsigncode "extract-signature"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/${ext}.der"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
set_tests_properties(removed_${ext} extract_pem_${ext} extract_der_${ext}
|
|
||||||
PROPERTIES DEPENDS sign_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
foreach(format ${sign_formats})
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
|
||||||
add_test(
|
|
||||||
NAME attached_${format}_${ext}
|
|
||||||
COMMAND osslsigncode "attach-signature" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
|
||||||
"-add-msi-dse" "-h" "sha512" "-nest"
|
|
||||||
"-sigin" "${FILES}/${ext}.${format}"
|
"-sigin" "${FILES}/${ext}.${format}"
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/attached_${format}.${ext}"
|
"-in" "${FILES}/signed.${ext}"
|
||||||
)
|
"-out" "${FILES}/attached_${format}.${ext}"
|
||||||
set_tests_properties(attached_${format}_${ext} PROPERTIES
|
# verify options
|
||||||
DEPENDS extract_pem_${ext}
|
"-require-leaf-hash" "FILE ${CERTS}/leafhash.txt"
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
REQUIRED_FILES "${FILES}/${ext}.${format}"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
)
|
"-CRLfile" "${CERTS}/CACertCRL.pem")
|
||||||
endforeach()
|
set_tests_properties("attached_${format}_${ext}" PROPERTIES
|
||||||
endforeach()
|
DEPENDS "signed_${ext};extract_pem_${ext};extract_der_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "attached_${format}_${ext}")
|
||||||
|
endforeach(format ${formats})
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
# Add an unauthenticated blob to a previously-signed file
|
||||||
add_test(
|
foreach(ext ${extensions_all})
|
||||||
NAME added_${ext}
|
add_test(NAME "added_${ext}"
|
||||||
COMMAND osslsigncode "add"
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "add"
|
||||||
"-addUnauthenticatedBlob" "-add-msi-dse" "-h" "sha512"
|
"-addUnauthenticatedBlob"
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/added.${ext}"
|
"-add-msi-dse" "-h" "sha512"
|
||||||
)
|
"-in" "${FILES}/signed.${ext}"
|
||||||
set_tests_properties(added_${ext} PROPERTIES
|
"-out" "${FILES}/added.${ext}")
|
||||||
DEPENDS sign_${ext}
|
set_tests_properties("added_${ext}" PROPERTIES
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
DEPENDS "signed_${ext}")
|
||||||
)
|
list(APPEND ALL_TESTS "added_${ext}")
|
||||||
endforeach()
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
# Add the new nested signature instead of replacing the first one
|
||||||
add_test(
|
# APPX files do not support nesting (multiple signature)
|
||||||
NAME nested_${ext}
|
foreach(ext ${extensions_all})
|
||||||
COMMAND osslsigncode "sign" "-nest" ${sign_opt} ${priv_der}
|
add_test(NAME "nested_${ext}"
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/nested.${ext}"
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
)
|
"-nest"
|
||||||
set_tests_properties(nested_${ext} PROPERTIES
|
"-certs" "${CERTS}/cert.pem"
|
||||||
DEPENDS sign_${ext}
|
"-key" "${CERTS}/key.der"
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
"-pass" "passme"
|
||||||
)
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
endforeach()
|
"-time" "1556755200" # Signing time: May 2 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha512"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/nested.${ext}")
|
||||||
|
set_tests_properties("nested_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "nested_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
foreach(file ${files_4})
|
### Verify signature ###
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
|
||||||
add_test(
|
|
||||||
NAME verify_${file}_${ext}
|
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
|
||||||
"-in" "${FILES}/${file}.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(verify_${file}_${ext} PROPERTIES
|
|
||||||
DEPENDS ${file}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/${file}.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(file ${files_3})
|
# Verify PE/MSI/CAB files signed in the catalog file
|
||||||
foreach(ext ${extensions_3})
|
# CAT and APPX files do not support detached PKCS#7 signature
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
foreach(ext ${extensions_nocatappx})
|
||||||
add_test(
|
add_test(NAME "verify_catalog_${ext}"
|
||||||
NAME verify_${file}_${ext}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
"-catalog" "${FILES}/signed.cat" # catalog file
|
||||||
"-time" "1567296000"
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
"-require-leaf-hash" "FILE ${CERTS}/leafhash.txt"
|
||||||
"-in" "${FILES}/${file}.${ext}"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
)
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
set_tests_properties(verify_${file}_${ext} PROPERTIES
|
"-in" "${FILES}/unsigned.${ext}")
|
||||||
DEPENDS ${file}_${ext}
|
set_tests_properties("verify_catalog_${ext}" PROPERTIES
|
||||||
REQUIRED_FILES "${FILES}/${file}.${ext}"
|
DEPENDS "signed_${ext}")
|
||||||
)
|
list(APPEND ALL_TESTS "verify_catalog_${ext}")
|
||||||
endforeach()
|
endforeach(ext ${extensions_nocatappx})
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
# Verify signature
|
||||||
set_tests_properties(verify_removed_${ext} PROPERTIES
|
set(files "signed" "nested" "added" "revoked")
|
||||||
WILL_FAIL TRUE
|
foreach(file ${files})
|
||||||
)
|
foreach(ext ${extensions_all})
|
||||||
endforeach()
|
add_test(NAME "verify_${file}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/${file}.${ext}")
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "${file}_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_${file}_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# "revoked" tests are expected to fail
|
||||||
|
set(files "revoked")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# Verify removed signature
|
||||||
|
# "removed" tests are expected to fail
|
||||||
|
# "remove-signature" command is unsupported for CAT files
|
||||||
|
set(files "removed")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
add_test(NAME "verify_${file}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/${file}.${ext}")
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "${file}_${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
list(APPEND ALL_TESTS "verify_${file}_${ext}")
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# Verify attached signature
|
||||||
|
# "attach-signature" command is unsupported for CAT files
|
||||||
|
set(files "attached_pem" "attached_der")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
add_test(NAME "verify_${file}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/${file}.${ext}")
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "${file}_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_${file}_${ext}")
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
|
||||||
if(Python3_FOUND)
|
### Extract a data content to be signed ###
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
|
# Unsupported command "extract-data" for CAT files
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
# Extract PKCS#7 with data content, output in PEM format
|
||||||
|
add_test(NAME "data_${ext}_pem"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-data"
|
||||||
|
"-ph"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-pem" # PEM format
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/data_${ext}.pem")
|
||||||
|
|
||||||
|
# Extract PKCS#7 with data content, output in default DER format
|
||||||
|
add_test(NAME "data_${ext}_der"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-data"
|
||||||
|
"-ph"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/data_${ext}.der")
|
||||||
|
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
set_tests_properties("data_${ext}_${data_format}" PROPERTIES
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "data_${ext}_${data_format}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
|
||||||
|
# Sign a data content, output in DER format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
add_test(NAME "signed_data_${ext}_${data_format}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-in" "${FILES}/data_${ext}.${data_format}"
|
||||||
|
"-out" "${FILES}/signed_data_${ext}_${data_format}.der")
|
||||||
|
set_tests_properties("signed_data_${ext}_${data_format}" PROPERTIES
|
||||||
|
DEPENDS "data_${ext}_pem;data_${ext}_der")
|
||||||
|
list(APPEND ALL_TESTS "signed_data_${ext}_${data_format}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
|
||||||
|
# Sign a data content, output in PEM format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
add_test(NAME "signed_data_pem_${ext}_${data_format}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-pem" # PEM format
|
||||||
|
"-in" "${FILES}/data_${ext}.${data_format}"
|
||||||
|
"-out" "${FILES}/signed_data_${ext}_${data_format}.pem")
|
||||||
|
set_tests_properties("signed_data_pem_${ext}_${data_format}" PROPERTIES
|
||||||
|
DEPENDS "data_${ext}_${data_format}")
|
||||||
|
list(APPEND ALL_TESTS "signed_data_pem_${ext}_${data_format}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
|
||||||
|
# Attach signature in PEM or DER format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
foreach(format ${formats})
|
||||||
|
add_test(NAME "attached_data_${ext}_${data_format}_${format}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "attach-signature"
|
||||||
|
# sign options
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-sigin" "${FILES}/signed_data_${ext}_${data_format}.${format}"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/attached_data_${data_format}_${format}.${ext}"
|
||||||
|
# verify options
|
||||||
|
"-require-leaf-hash" "FILE ${CERTS}/leafhash.txt"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem")
|
||||||
|
set_tests_properties("attached_data_${ext}_${data_format}_${format}" PROPERTIES
|
||||||
|
DEPENDS "signed_data_${ext}_${data_format};signed_data_pem_${ext}_${data_format}")
|
||||||
|
list(APPEND ALL_TESTS "attached_data_${ext}_${data_format}_${format}")
|
||||||
|
endforeach(format ${formats})
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
|
|
||||||
|
if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0" OR CURL_FOUND)
|
||||||
|
|
||||||
|
### Sign with Time-Stamp Authority ###
|
||||||
|
|
||||||
|
# Sign with the RFC3161 Time-Stamp Authority
|
||||||
|
set(pem_certs "cert" "expired" "revoked")
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
foreach(cert ${pem_certs})
|
foreach(cert ${pem_certs})
|
||||||
add_test(
|
add_test(NAME "sign_ts_${cert}_${ext}"
|
||||||
NAME sign_ts_${cert}_${ext}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
COMMAND ${Python3_EXECUTABLE} "${PROJECT_BINARY_DIR}/Testing/tsa_server.py"
|
"-certs" "${CERTS}/${cert}.pem"
|
||||||
"--certs" "${CERTS}/${cert}.pem" "--key" "${CERTS}/key.pem"
|
"-key" "${CERTS}/key.pem"
|
||||||
"--input" "${FILES}/unsigned.${ext}" "--output" "${FILES}/ts_${cert}.${ext}"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
)
|
"-comm"
|
||||||
endforeach()
|
"-ph"
|
||||||
endforeach()
|
"-jp" "low"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-ts" "FILE ${LOGS}/url.log"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/ts_${cert}.${ext}")
|
||||||
|
set_tests_properties("sign_ts_${cert}_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy="
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "sign_ts_${cert}_${ext}")
|
||||||
|
endforeach(cert ${pem_certs})
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
|
### Verify Time-Stamp Authority ###
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
add_test(
|
foreach(ext ${extensions_all})
|
||||||
NAME verify_ts_cert_${ext}
|
add_test(NAME "verify_ts_cert_${ext}"
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
"-time" "1567296000"
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
"-in" "${FILES}/ts_cert.${ext}"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
)
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
set_tests_properties(verify_ts_cert_${ext} PROPERTIES
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
set_tests_properties("verify_ts_cert_${ext}" PROPERTIES
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
)
|
DEPENDS "sign_ts_cert_${ext}")
|
||||||
endforeach()
|
list(APPEND ALL_TESTS "verify_ts_cert_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
foreach(ext ${extensions_4})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(NAME "verify_ts_future_${ext}"
|
||||||
NAME verify_ts_future_${ext}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
"-time" "2051222400" # Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
"-time" "2051222400"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
"-in" "${FILES}/ts_cert.${ext}"
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
)
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
set_tests_properties(verify_ts_future_${ext} PROPERTIES
|
set_tests_properties("verify_ts_future_${ext}" PROPERTIES
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
DEPENDS "sign_ts_cert_${ext}")
|
||||||
)
|
list(APPEND ALL_TESTS "verify_ts_future_${ext}")
|
||||||
endforeach()
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
# Verify with ignored timestamp
|
||||||
# enabled "-ignore-timestamp" option
|
# This tests are expected to fail
|
||||||
foreach(ext ${extensions_4})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(NAME "verify_ts_ignore_${ext}"
|
||||||
NAME verify_ts_ignore_${ext}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
"-time" "2051222400" # Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
"-time" "2051222400"
|
|
||||||
"-ignore-timestamp"
|
"-ignore-timestamp"
|
||||||
"-in" "${FILES}/ts_cert.${ext}"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
)
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
set_tests_properties(verify_ts_ignore_${ext} PROPERTIES
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
set_tests_properties("verify_ts_ignore_${ext}" PROPERTIES
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
WILL_FAIL TRUE
|
DEPENDS "sign_ts_cert_${ext}"
|
||||||
)
|
WILL_FAIL TRUE)
|
||||||
endforeach()
|
list(APPEND ALL_TESTS "verify_ts_ignore_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
|
### Verify CRL Distribution Points ###
|
||||||
|
|
||||||
|
# Verify file signed with X509v3 CRL Distribution Points extension
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
# Certificate has expired or revoked
|
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
||||||
foreach(ext ${extensions_4})
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_cert_crldp_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
|
set_tests_properties("verify_ts_cert_crldp_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_cert_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_cert_crldp_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Verify with expired or revoked certificate, ignore X509v3 CRL Distribution Points extension
|
||||||
|
# This tests are expected to fail
|
||||||
|
set(failed_certs "expired" "revoked")
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
foreach(cert ${failed_certs})
|
foreach(cert ${failed_certs})
|
||||||
add_test(
|
add_test(NAME "verify_ts_${cert}_${ext}"
|
||||||
NAME verify_ts_${cert}_${ext}
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
"-time" "1567296000"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
"-in" "${FILES}/ts_${cert}.${ext}"
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
)
|
"-ignore-cdp"
|
||||||
set_tests_properties(verify_ts_${cert}_${ext} PROPERTIES
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
"-in" "${FILES}/ts_${cert}.${ext}")
|
||||||
REQUIRED_FILES "${FILES}/ts_${cert}.${ext}"
|
set_tests_properties("verify_ts_${cert}_${ext}" PROPERTIES
|
||||||
WILL_FAIL TRUE
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
)
|
DEPENDS "sign_ts_${cert}_${ext}"
|
||||||
endforeach()
|
WILL_FAIL TRUE)
|
||||||
endforeach()
|
list(APPEND ALL_TESTS "verify_ts_${cert}_${ext}")
|
||||||
|
endforeach(cert ${failed_certs})
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
else()
|
# Verify with revoked certificate contains X509v3 CRL Distribution Points extension
|
||||||
message(STATUS "Python3 was not found, skip timestamping tests")
|
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
||||||
endif()
|
# This test is expected to fail
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_revoked_crldp_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_revoked.${ext}")
|
||||||
|
set_tests_properties("verify_ts_revoked_crldp_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_revoked_${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_revoked_crldp_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
### Cleanup ###
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/signed.${ext}")
|
# Stop HTTP server
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/nested.${ext}")
|
if(STOP_SERVER)
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/removed.${ext}")
|
add_test(NAME "stop_server"
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/added.${ext}")
|
COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/client_http.py")
|
||||||
|
set_tests_properties("stop_server" PROPERTIES
|
||||||
|
DEPENDS "${ALL_TESTS}")
|
||||||
|
list(APPEND ALL_TESTS "stop_server")
|
||||||
|
else(STOP_SERVER)
|
||||||
|
message(STATUS "Keep HTTP server after tests")
|
||||||
|
endif(STOP_SERVER)
|
||||||
|
|
||||||
|
else(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0" OR CURL_FOUND)
|
||||||
|
message(STATUS "CTest skips some tests")
|
||||||
|
endif(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0" OR CURL_FOUND)
|
||||||
|
|
||||||
|
# Delete test files
|
||||||
|
set(names "signed" "nested" "revoked" "removed" "added")
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
foreach(name ${names})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${name}.${ext}")
|
||||||
|
endforeach(name ${names})
|
||||||
foreach(cert ${pem_certs})
|
foreach(cert ${pem_certs})
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/ts_${cert}.${ext}")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/ts_${cert}.${ext}")
|
||||||
endforeach()
|
endforeach(cert ${pem_certs})
|
||||||
foreach(format ${sign_formats})
|
foreach(format ${formats})
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/attached_${format}.${ext}")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/attached_${format}.${ext}")
|
||||||
endforeach()
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/data_${ext}.${format}")
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/signed_data_${ext}_${format}.${data_format}")
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/attached_data_${data_format}_${format}.${ext}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
endforeach(format ${formats})
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jreq.tsq")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jreq.tsq")
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jresp.tsr")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jresp.tsr")
|
||||||
endforeach()
|
endforeach(ext ${extensions_all})
|
||||||
add_test(NAME remove_files COMMAND ${CMAKE_COMMAND} -E rm -f ${OUTPUT_FILES})
|
|
||||||
|
add_test(NAME "remove_files"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rm -f ${OUTPUT_FILES})
|
||||||
|
|
||||||
|
set_tests_properties("remove_files" PROPERTIES
|
||||||
|
DEPENDS "${ALL_TESTS}")
|
||||||
|
|
||||||
|
endif(Python3_FOUND AND NOT cryptography_error)
|
||||||
|
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(UNIX)
|
||||||
check_function_exists(getpass HAVE_GETPASS)
|
check_function_exists(getpass HAVE_GETPASS)
|
||||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||||
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
|
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
|
||||||
if(HAVE_SYS_MMAN_H)
|
if(HAVE_SYS_MMAN_H)
|
||||||
check_function_exists(mmap HAVE_MMAP)
|
check_function_exists(mmap HAVE_MMAP)
|
||||||
if(NOT HAVE_MMAP)
|
endif(HAVE_SYS_MMAN_H)
|
||||||
message(FATAL_ERROR "Error: Need mmap to build.")
|
else(UNIX)
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# include wincrypt.h in Windows.h
|
|
||||||
if(MSVC AND NOT CYGWIN)
|
|
||||||
check_include_file(windows.h HAVE_MAPVIEWOFFILE)
|
check_include_file(windows.h HAVE_MAPVIEWOFFILE)
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
if(NOT (HAVE_MMAP OR HAVE_MAPVIEWOFFILE))
|
if(NOT (HAVE_MMAP OR HAVE_MAPVIEWOFFILE))
|
||||||
message(FATAL_ERROR "Error: Need file mapping function to build.")
|
message(FATAL_ERROR "Error: Need file mapping function to build.")
|
||||||
endif()
|
endif(NOT (HAVE_MMAP OR HAVE_MAPVIEWOFFILE))
|
||||||
endif()
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
@ -1,13 +1,32 @@
|
|||||||
|
# This list describes the default variables included in the bash-completion package:
|
||||||
|
# BASH_COMPLETION_VERSION "@VERSION@"
|
||||||
|
# BASH_COMPLETION_PREFIX "@prefix@"
|
||||||
|
# BASH_COMPLETION_COMPATDIR "@sysconfdir@/bash_completion.d"
|
||||||
|
# BASH_COMPLETION_COMPLETIONSDIR "@datadir@/@PACKAGE@/completions"
|
||||||
|
# BASH_COMPLETION_HELPERSDIR "@datadir@/@PACKAGE@/helpers"
|
||||||
|
# BASH_COMPLETION_FOUND "TRUE"
|
||||||
|
# https://github.com/scop/bash-completion/blob/master/bash-completion-config.cmake.in
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
|
if(BASH_COMPLETION_USER_DIR)
|
||||||
|
set(BASH_COMPLETION_COMPLETIONSDIR "${BASH_COMPLETION_USER_DIR}/bash-completion/completions")
|
||||||
|
else(BASH_COMPLETION_USER_DIR)
|
||||||
find_package(bash-completion QUIET)
|
find_package(bash-completion QUIET)
|
||||||
if(NOT BASH_COMPLETION_COMPLETIONSDIR)
|
if(NOT BASH_COMPLETION_FOUND)
|
||||||
if(BASH_COMPLETION_COMPATDIR)
|
|
||||||
set(BASH_COMPLETION_COMPLETIONSDIR ${BASH_COMPLETION_COMPATDIR})
|
|
||||||
else()
|
|
||||||
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share")
|
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share")
|
||||||
set(BASH_COMPLETION_COMPLETIONSDIR "${SHAREDIR}/bash-completion/completions")
|
set(BASH_COMPLETION_COMPLETIONSDIR "${SHAREDIR}/bash-completion/completions")
|
||||||
endif()
|
endif(NOT BASH_COMPLETION_FOUND)
|
||||||
endif()
|
endif(BASH_COMPLETION_USER_DIR)
|
||||||
|
|
||||||
message(STATUS "Using bash completions dir ${BASH_COMPLETION_COMPLETIONSDIR}")
|
message(STATUS "Using bash completions dir ${BASH_COMPLETION_COMPLETIONSDIR}")
|
||||||
install(FILES "osslsigncode.bash" DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR})
|
install(FILES "osslsigncode.bash" DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR})
|
||||||
endif()
|
endif(NOT MSVC)
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
@ -7,9 +7,9 @@ function(add_debug_flag_if_supported flagname targets)
|
|||||||
if (HAVE_FLAG_${flagname})
|
if (HAVE_FLAG_${flagname})
|
||||||
foreach(target ${targets})
|
foreach(target ${targets})
|
||||||
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:${flagname}>)
|
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:${flagname}>)
|
||||||
endforeach()
|
endforeach(target ${targets})
|
||||||
endif()
|
endif(HAVE_FLAG_${flagname})
|
||||||
endfunction()
|
endfunction(add_debug_flag_if_supported flagname targets)
|
||||||
|
|
||||||
function(add_compile_flag_to_targets targets)
|
function(add_compile_flag_to_targets targets)
|
||||||
set(CHECKED_DEBUG_FLAGS
|
set(CHECKED_DEBUG_FLAGS
|
||||||
@ -44,12 +44,11 @@ function(add_compile_flag_to_targets targets)
|
|||||||
"-Wmisleading-indentation"
|
"-Wmisleading-indentation"
|
||||||
"-Wabsolute-value"
|
"-Wabsolute-value"
|
||||||
"-Wunused-parameter"
|
"-Wunused-parameter"
|
||||||
"-Wunused-function"
|
"-Wunused-function")
|
||||||
)
|
|
||||||
foreach(flag ${CHECKED_DEBUG_FLAGS})
|
foreach(flag ${CHECKED_DEBUG_FLAGS})
|
||||||
add_debug_flag_if_supported(${flag} ${targets})
|
add_debug_flag_if_supported(${flag} ${targets})
|
||||||
endforeach()
|
endforeach(flag ${CHECKED_DEBUG_FLAGS})
|
||||||
endfunction()
|
endfunction(add_compile_flag_to_targets targets)
|
||||||
|
|
||||||
function(add_compile_flags target)
|
function(add_compile_flags target)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
@ -76,36 +75,49 @@ function(add_compile_flags target)
|
|||||||
# Enable generation of EH Continuation (EHCONT) metadata by the compiler
|
# Enable generation of EH Continuation (EHCONT) metadata by the compiler
|
||||||
#target_compile_options(${target} PRIVATE /guard:ehcont)
|
#target_compile_options(${target} PRIVATE /guard:ehcont)
|
||||||
#target_link_options(${target} PRIVATE /guard:ehcont)
|
#target_link_options(${target} PRIVATE /guard:ehcont)
|
||||||
else()
|
else("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
# Can handle addresses larger than 2 gigabytes
|
# Can handle addresses larger than 2 gigabytes
|
||||||
target_link_options(${target} PRIVATE /LARGEADDRESSAWARE)
|
target_link_options(${target} PRIVATE /LARGEADDRESSAWARE)
|
||||||
# Safe structured exception handlers (x86 only)
|
# Safe structured exception handlers (x86 only)
|
||||||
target_link_options(${target} PRIVATE /SAFESEH)
|
target_link_options(${target} PRIVATE /SAFESEH)
|
||||||
endif()
|
endif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/D_FORTIFY_SOURCE=2>)
|
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/D_FORTIFY_SOURCE=2>)
|
||||||
# Unrecognized compiler options are errors
|
# Unrecognized compiler options are errors
|
||||||
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/options:strict>)
|
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/options:strict>)
|
||||||
else()
|
else(MSVC)
|
||||||
check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
|
check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
|
||||||
if(HAVE_STACK_PROTECTOR_ALL)
|
if(HAVE_STACK_PROTECTOR_ALL)
|
||||||
target_link_options(${target} PRIVATE -fstack-protector-all)
|
target_link_options(${target} PRIVATE -fstack-protector-all)
|
||||||
else()
|
else(HAVE_STACK_PROTECTOR_ALL)
|
||||||
check_c_compiler_flag("-fstack-protector" HAVE_STACK_PROTECTOR)
|
check_c_compiler_flag("-fstack-protector" HAVE_STACK_PROTECTOR)
|
||||||
if(HAVE_STACK_PROTECTOR)
|
if(HAVE_STACK_PROTECTOR)
|
||||||
target_link_options(${target} PRIVATE -fstack-protector)
|
target_link_options(${target} PRIVATE -fstack-protector)
|
||||||
else()
|
else(HAVE_STACK_PROTECTOR)
|
||||||
message(WARNING "No stack protection supported")
|
message(WARNING "No stack protection supported")
|
||||||
endif()
|
endif(HAVE_STACK_PROTECTOR)
|
||||||
endif()
|
endif(HAVE_STACK_PROTECTOR_ALL)
|
||||||
# Support address space layout randomization (ASLR)
|
# Support address space layout randomization (ASLR)
|
||||||
target_compile_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-fPIE>)
|
if(NOT (MINGW OR CYGWIN OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-fPIE -pie>)
|
OR ((CMAKE_SYSTEM_NAME MATCHES Darwin) AND (CMAKE_C_COMPILER_ID MATCHES Clang))))
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-Wl,-z,relro>)
|
target_compile_options(${target} PRIVATE -fPIE)
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-Wl,-z,now>)
|
target_link_options(${target} PRIVATE -fPIE -pie)
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-Wl,-z,noexecstack>)
|
target_link_options(${target} PRIVATE -Wl,-z,relro)
|
||||||
|
target_link_options(${target} PRIVATE -Wl,-z,now)
|
||||||
|
target_link_options(${target} PRIVATE -Wl,-z,noexecstack)
|
||||||
|
endif(NOT (MINGW OR CYGWIN OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
|
||||||
|
OR ((CMAKE_SYSTEM_NAME MATCHES Darwin) AND (CMAKE_C_COMPILER_ID MATCHES Clang))))
|
||||||
target_link_options(${target} PRIVATE -fstack-check)
|
target_link_options(${target} PRIVATE -fstack-check)
|
||||||
add_compile_flag_to_targets(${target})
|
add_compile_flag_to_targets(${target})
|
||||||
endif()
|
endif(MSVC)
|
||||||
endfunction()
|
endfunction(add_compile_flags target)
|
||||||
|
|
||||||
add_compile_flags(osslsigncode)
|
add_compile_flags(osslsigncode)
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
9038
code_signing_ca.pem
Normal file
9038
code_signing_ca.pem
Normal file
File diff suppressed because it is too large
Load Diff
41
get_code_signing_ca.py
Executable file
41
get_code_signing_ca.py
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# © 2024 Michal Trojnara
|
||||||
|
# This script downloads Microsoft code signing certificates
|
||||||
|
# Tor is required for this script to work
|
||||||
|
# Redirect the script output to a PEM file
|
||||||
|
|
||||||
|
from sys import stderr
|
||||||
|
from time import sleep
|
||||||
|
from csv import reader
|
||||||
|
from requests import get
|
||||||
|
from requests.exceptions import RequestException
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
|
def download_cert(hash):
|
||||||
|
for attempt in range(10):
|
||||||
|
if attempt > 0:
|
||||||
|
sleep(10)
|
||||||
|
try:
|
||||||
|
creds = f'{attempt}{hash}:{attempt}{hash}'
|
||||||
|
resp = get(f'https://crt.sh/?d={hash}',
|
||||||
|
proxies=dict(https=f'socks5://{creds}@127.0.0.1:9050'))
|
||||||
|
resp.raise_for_status()
|
||||||
|
print('.', file=stderr, end='')
|
||||||
|
stderr.flush()
|
||||||
|
return resp.content.decode('utf-8')
|
||||||
|
except RequestException as e:
|
||||||
|
print(f'\nAttempt {attempt}: {e}', file=stderr)
|
||||||
|
print('\nGiving up on', hash, file=stderr)
|
||||||
|
|
||||||
|
resp = get('https://ccadb-public.secure.force.com/microsoft/IncludedCACertificateReportForMSFTCSV')
|
||||||
|
resp.raise_for_status()
|
||||||
|
lines = resp.content.decode('utf-8').splitlines()[1:]
|
||||||
|
hashes = [row[4] for row in reader(lines)
|
||||||
|
if row[0] != 'Disabled'
|
||||||
|
or row[4] == 'F38406E540D7A9D90CB4A9479299640FFB6DF9E224ECC7A01C0D9558D8DAD77D']
|
||||||
|
with ThreadPoolExecutor(max_workers=20) as executor:
|
||||||
|
certs = executor.map(download_cert, hashes)
|
||||||
|
for cert in certs:
|
||||||
|
if cert is not None:
|
||||||
|
print(cert)
|
||||||
|
print('\nDone', file=stderr)
|
807
helpers.c
Normal file
807
helpers.c
Normal file
@ -0,0 +1,807 @@
|
|||||||
|
/*
|
||||||
|
* osslsigncode support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osslsigncode.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_sequence_number(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
||||||
|
static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer);
|
||||||
|
static int X509_compare(const X509 *const *a, const X509 *const *b);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] infile
|
||||||
|
* [returns] file size
|
||||||
|
*/
|
||||||
|
uint32_t get_file_size(const char *infile)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct _stat64 st;
|
||||||
|
ret = _stat64(infile, &st);
|
||||||
|
#else
|
||||||
|
struct stat st;
|
||||||
|
ret = stat(infile, &st);
|
||||||
|
#endif
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Failed to open file: %s\n", infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size < 4) {
|
||||||
|
fprintf(stderr, "Unrecognized file type - file is too short: %s\n", infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (st.st_size > UINT32_MAX) {
|
||||||
|
fprintf(stderr, "Unsupported file - too large: %s\n", infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (uint32_t)st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] infile: starting address for the new mapping
|
||||||
|
* [returns] pointer to the mapped area
|
||||||
|
*/
|
||||||
|
char *map_file(const char *infile, const size_t size)
|
||||||
|
{
|
||||||
|
char *indata = NULL;
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE fhandle, fmap;
|
||||||
|
(void)size;
|
||||||
|
fhandle = CreateFile(infile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (fhandle == INVALID_HANDLE_VALUE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fmap = CreateFileMapping(fhandle, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
|
CloseHandle(fhandle);
|
||||||
|
if (fmap == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
indata = (char *)MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
CloseHandle(fmap);
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
int fd = open(infile, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
indata = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (indata == MAP_FAILED) {
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "No file mapping function\n");
|
||||||
|
return NULL;
|
||||||
|
#endif /* HAVE_SYS_MMAN_H */
|
||||||
|
#endif /* WIN32 */
|
||||||
|
return indata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] indata: starting address space
|
||||||
|
* [in] size: mapped area length
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
void unmap_file(char *indata, const size_t size)
|
||||||
|
{
|
||||||
|
if (!indata)
|
||||||
|
return;
|
||||||
|
#ifdef WIN32
|
||||||
|
(void)size;
|
||||||
|
UnmapViewOfFile(indata);
|
||||||
|
#else
|
||||||
|
munmap(indata, size);
|
||||||
|
#endif /* WIN32 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve a decoded PKCS#7 structure
|
||||||
|
* [in] data: encoded PEM or DER data
|
||||||
|
* [in] size: data size
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
PKCS7 *pkcs7_read_data(char *data, uint32_t size)
|
||||||
|
{
|
||||||
|
PKCS7 *p7 = NULL;
|
||||||
|
BIO *bio;
|
||||||
|
const char pemhdr[] = "-----BEGIN PKCS7-----";
|
||||||
|
|
||||||
|
bio = BIO_new_mem_buf(data, (int)size);
|
||||||
|
if (size >= sizeof pemhdr && !memcmp(data, pemhdr, sizeof pemhdr - 1)) {
|
||||||
|
/* PEM format */
|
||||||
|
p7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
|
||||||
|
} else { /* DER format */
|
||||||
|
p7 = d2i_PKCS7_bio(bio, NULL);
|
||||||
|
}
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] outdata: BIO outdata file
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
(void)BIO_reset(outdata);
|
||||||
|
if (ctx->options->output_pkcs7) {
|
||||||
|
/* PEM format */
|
||||||
|
ret = !PEM_write_bio_PKCS7(outdata, p7);
|
||||||
|
} else {
|
||||||
|
/* default DER format */
|
||||||
|
ret = !i2d_PKCS7_bio(outdata, p7);
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Unable to write pkcs7 object\n");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate, set type, add content and return a new PKCS#7 signature
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
int i, signer = -1;
|
||||||
|
PKCS7 *p7;
|
||||||
|
PKCS7_SIGNER_INFO *si = NULL;
|
||||||
|
STACK_OF(X509) *chain = NULL;
|
||||||
|
|
||||||
|
p7 = PKCS7_new();
|
||||||
|
PKCS7_set_type(p7, NID_pkcs7_signed);
|
||||||
|
PKCS7_content_new(p7, NID_pkcs7_data);
|
||||||
|
if (ctx->options->cert != NULL) {
|
||||||
|
/*
|
||||||
|
* the private key and corresponding certificate are parsed from the PKCS12
|
||||||
|
* structure or loaded from the security token, so we may omit to check
|
||||||
|
* the consistency of a private key with the public key in an X509 certificate
|
||||||
|
*/
|
||||||
|
si = PKCS7_add_signature(p7, ctx->options->cert, ctx->options->pkey,
|
||||||
|
ctx->options->md);
|
||||||
|
if (si == NULL)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
} else {
|
||||||
|
/* find the signer's certificate located somewhere in the whole certificate chain */
|
||||||
|
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
|
||||||
|
X509 *signcert = sk_X509_value(ctx->options->certs, i);
|
||||||
|
if (X509_check_private_key(signcert, ctx->options->pkey)) {
|
||||||
|
si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
|
||||||
|
signer = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (si == NULL) {
|
||||||
|
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
|
||||||
|
ctx->options->keyfile);
|
||||||
|
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
|
||||||
|
ctx->options->certfile);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pkcs7_signer_info_add_signing_time(si, ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!pkcs7_signer_info_add_purpose(si, ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if ((ctx->options->desc || ctx->options->url) &&
|
||||||
|
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
|
||||||
|
fprintf(stderr, "Couldn't allocate memory for opus info\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if ((ctx->options->nested_number >= 0) &&
|
||||||
|
!pkcs7_signer_info_add_sequence_number(si, ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
/* create X509 chain sorted in ascending order by their DER encoding */
|
||||||
|
chain = X509_chain_get_sorted(ctx, signer);
|
||||||
|
if (chain == NULL) {
|
||||||
|
fprintf(stderr, "Failed to create a sorted certificate chain\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
/* add sorted certificate chain */
|
||||||
|
for (i=0; i<sk_X509_num(chain); i++) {
|
||||||
|
PKCS7_add_certificate(p7, sk_X509_value(chain, i));
|
||||||
|
}
|
||||||
|
/* add crls */
|
||||||
|
if (ctx->options->crls) {
|
||||||
|
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
|
||||||
|
PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
|
||||||
|
}
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return p7; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PE, MSI, CAB and APPX file specific
|
||||||
|
* Add "1.3.6.1.4.1.311.2.1.4" SPC_INDIRECT_DATA_OBJID signed attribute
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int add_indirect_data_object(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
|
PKCS7_SIGNER_INFO *si;
|
||||||
|
|
||||||
|
signer_info = PKCS7_get_signer_info(p7);
|
||||||
|
if (!signer_info)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
|
||||||
|
V_ASN1_OBJECT, OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1)))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PE, MSI, CAB and APPX format specific
|
||||||
|
* Sign the MS Authenticode spcIndirectDataContent blob.
|
||||||
|
* The spcIndirectDataContent structure is used in Authenticode signatures
|
||||||
|
* to store the digest and other attributes of the signed file.
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] content: spcIndirectDataContent
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int sign_spc_indirect_data_content(PKCS7 *p7, ASN1_OCTET_STRING *content)
|
||||||
|
{
|
||||||
|
int len, inf, tag, class;
|
||||||
|
long plen;
|
||||||
|
const u_char *data, *p;
|
||||||
|
PKCS7 *td7;
|
||||||
|
|
||||||
|
p = data = ASN1_STRING_get0_data(content);
|
||||||
|
len = ASN1_STRING_length(content);
|
||||||
|
inf = ASN1_get_object(&p, &plen, &tag, &class, len);
|
||||||
|
if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE
|
||||||
|
|| !pkcs7_sign_content(p7, p, (int)plen)) {
|
||||||
|
fprintf(stderr, "Failed to sign spcIndirectDataContent\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
td7 = PKCS7_new();
|
||||||
|
if (!td7) {
|
||||||
|
fprintf(stderr, "PKCS7_new failed\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
td7->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1);
|
||||||
|
td7->d.other = ASN1_TYPE_new();
|
||||||
|
td7->d.other->type = V_ASN1_SEQUENCE;
|
||||||
|
td7->d.other->value.sequence = ASN1_STRING_new();
|
||||||
|
ASN1_STRING_set(td7->d.other->value.sequence, data, len);
|
||||||
|
if (!PKCS7_set_content(p7, td7)) {
|
||||||
|
fprintf(stderr, "PKCS7_set_content failed\n");
|
||||||
|
PKCS7_free(td7);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add encapsulated content to signed PKCS7 structure.
|
||||||
|
* [in] content: spcIndirectDataContent
|
||||||
|
* [returns] new PKCS#7 signature with encapsulated content
|
||||||
|
*/
|
||||||
|
PKCS7 *pkcs7_set_content(ASN1_OCTET_STRING *content)
|
||||||
|
{
|
||||||
|
PKCS7 *p7, *td7;
|
||||||
|
|
||||||
|
p7 = PKCS7_new();
|
||||||
|
if (!p7) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!PKCS7_set_type(p7, NID_pkcs7_signed)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!PKCS7_content_new(p7, NID_pkcs7_data)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
td7 = PKCS7_new();
|
||||||
|
if (!td7) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
td7->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1);
|
||||||
|
td7->d.other = ASN1_TYPE_new();
|
||||||
|
td7->d.other->type = V_ASN1_SEQUENCE;
|
||||||
|
td7->d.other->value.sequence = content;
|
||||||
|
if (!PKCS7_set_content(p7, td7)) {
|
||||||
|
PKCS7_free(td7);
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return spcIndirectDataContent.
|
||||||
|
* [in] hash: message digest BIO
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] content
|
||||||
|
*/
|
||||||
|
ASN1_OCTET_STRING *spc_indirect_data_content_get(BIO *hash, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
u_char mdbuf[5 * EVP_MAX_MD_SIZE + 24];
|
||||||
|
int mdlen, hashlen, len = 0;
|
||||||
|
u_char *data, *p = NULL;
|
||||||
|
|
||||||
|
content = ASN1_OCTET_STRING_new();
|
||||||
|
if (!content) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!spc_indirect_data_content_create(&p, &len, ctx)) {
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
hashlen = ctx->format->hash_length_get(ctx);
|
||||||
|
if (hashlen > EVP_MAX_MD_SIZE) {
|
||||||
|
/* APPX format specific */
|
||||||
|
mdlen = BIO_read(hash, (char*)mdbuf, hashlen);
|
||||||
|
} else {
|
||||||
|
mdlen = BIO_gets(hash, (char*)mdbuf, EVP_MAX_MD_SIZE);
|
||||||
|
}
|
||||||
|
data = OPENSSL_malloc((size_t)(len + mdlen));
|
||||||
|
memcpy(data, p, (size_t)len);
|
||||||
|
OPENSSL_free(p);
|
||||||
|
memcpy(data + len, mdbuf, (size_t)mdlen);
|
||||||
|
if (!ASN1_OCTET_STRING_set(content, data, len + mdlen)) {
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
OPENSSL_free(data);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(data);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signs the data and place the signature in p7
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] data: content data
|
||||||
|
* [in] len: content length
|
||||||
|
*/
|
||||||
|
int pkcs7_sign_content(PKCS7 *p7, const u_char *data, int len)
|
||||||
|
{
|
||||||
|
BIO *p7bio;
|
||||||
|
|
||||||
|
if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
|
||||||
|
fprintf(stderr, "PKCS7_dataInit failed\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_write(p7bio, data, len);
|
||||||
|
(void)BIO_flush(p7bio);
|
||||||
|
if (!PKCS7_dataFinal(p7, p7bio)) {
|
||||||
|
fprintf(stderr, "PKCS7_dataFinal failed\n");
|
||||||
|
BIO_free_all(p7bio);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_free_all(p7bio);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the header length (tag and length octets) of the ASN.1 type
|
||||||
|
* [in] p: ASN.1 data
|
||||||
|
* [in] len: ASN.1 data length
|
||||||
|
* [returns] header length
|
||||||
|
*/
|
||||||
|
int asn1_simple_hdr_len(const u_char *p, int len)
|
||||||
|
{
|
||||||
|
if (len <= 2 || p[0] > 0x31)
|
||||||
|
return 0;
|
||||||
|
return (p[1]&0x80) ? (2 + (p[1]&0x7f)) : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] hash: BIO with message digest method
|
||||||
|
* [in] indata: starting address space
|
||||||
|
* [in] idx: offset
|
||||||
|
* [in] fileend: the length of the hashed area
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int bio_hash_data(BIO *hash, char *indata, size_t idx, size_t fileend)
|
||||||
|
{
|
||||||
|
while (idx < fileend) {
|
||||||
|
size_t want, written;
|
||||||
|
want = fileend - idx;
|
||||||
|
if (want > SIZE_64K)
|
||||||
|
want = SIZE_64K;
|
||||||
|
if (!BIO_write_ex(hash, indata + idx, want, &written))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
idx += written;
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] descript1, descript2: descriptions
|
||||||
|
* [in] mdbuf: message digest
|
||||||
|
* [in] len: message digest length
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
void print_hash(const char *descript1, const char *descript2, const u_char *mdbuf, int len)
|
||||||
|
{
|
||||||
|
char *hexbuf = NULL;
|
||||||
|
int size, i, j = 0;
|
||||||
|
|
||||||
|
size = 2 * len + 1;
|
||||||
|
hexbuf = OPENSSL_malloc((size_t)size);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
#ifdef WIN32
|
||||||
|
j += sprintf_s(hexbuf + j, size - j, "%02X", mdbuf[i]);
|
||||||
|
#else
|
||||||
|
j += sprintf(hexbuf + j, "%02X", mdbuf[i]);
|
||||||
|
#endif /* WIN32 */
|
||||||
|
}
|
||||||
|
printf("%s: %s %s\n", descript1, hexbuf, descript2);
|
||||||
|
OPENSSL_free(hexbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] p7: new PKCS#7 signature
|
||||||
|
* [in] objid: Microsoft OID Authenticode
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int is_content_type(PKCS7 *p7, const char *objid)
|
||||||
|
{
|
||||||
|
ASN1_OBJECT *indir_objid;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
indir_objid = OBJ_txt2obj(objid, 1);
|
||||||
|
ret = p7 && PKCS7_type_is_signed(p7) &&
|
||||||
|
!OBJ_cmp(p7->d.sign->contents->type, indir_objid) &&
|
||||||
|
(p7->d.sign->contents->d.other->type == V_ASN1_SEQUENCE ||
|
||||||
|
p7->d.sign->contents->d.other->type == V_ASN1_OCTET_STRING);
|
||||||
|
ASN1_OBJECT_free(indir_objid);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] p7: new PKCS#7 signature
|
||||||
|
* [returns] pointer to MsCtlContent structure
|
||||||
|
*/
|
||||||
|
MsCtlContent *ms_ctl_content_get(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
ASN1_STRING *value;
|
||||||
|
const u_char *data;
|
||||||
|
|
||||||
|
if (!is_content_type(p7, MS_CTL_OBJID)) {
|
||||||
|
fprintf(stderr, "Failed to find MS_CTL_OBJID\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
value = p7->d.sign->contents->d.other->value.sequence;
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
return d2i_MsCtlContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] attribute: catalog attribute
|
||||||
|
* [returns] catalog content
|
||||||
|
*/
|
||||||
|
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute)
|
||||||
|
{
|
||||||
|
ASN1_STRING *value;
|
||||||
|
STACK_OF(ASN1_TYPE) *contents;
|
||||||
|
ASN1_TYPE *content;
|
||||||
|
const u_char *contents_data;
|
||||||
|
|
||||||
|
value = attribute->contents->value.sequence;
|
||||||
|
contents_data = ASN1_STRING_get0_data(value);
|
||||||
|
contents = d2i_ASN1_SET_ANY(NULL, &contents_data, ASN1_STRING_length(value));
|
||||||
|
if (!contents)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
content = sk_ASN1_TYPE_value(contents, 0);
|
||||||
|
sk_ASN1_TYPE_free(contents);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PE and CAB format specific
|
||||||
|
* [in] none
|
||||||
|
* [returns] pointer to SpcLink
|
||||||
|
*/
|
||||||
|
SpcLink *spc_link_obsolete_get(void)
|
||||||
|
{
|
||||||
|
const u_char obsolete[] = {
|
||||||
|
0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x4f,
|
||||||
|
0x00, 0x62, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c,
|
||||||
|
0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x3e,
|
||||||
|
0x00, 0x3e, 0x00, 0x3e
|
||||||
|
};
|
||||||
|
SpcLink *link = SpcLink_new();
|
||||||
|
link->type = 2;
|
||||||
|
link->value.file = SpcString_new();
|
||||||
|
link->value.file->type = 0;
|
||||||
|
link->value.file->value.unicode = ASN1_BMPSTRING_new();
|
||||||
|
ASN1_STRING_set(link->value.file->value.unicode, obsolete, sizeof obsolete);
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] mdbuf, cmdbuf: message digests
|
||||||
|
* [in] mdtype: message digest algorithm type
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype)
|
||||||
|
{
|
||||||
|
int mdlen = EVP_MD_size(EVP_get_digestbynid(mdtype));
|
||||||
|
int mdok = !memcmp(mdbuf, cmdbuf, (size_t)mdlen);
|
||||||
|
printf("Message digest algorithm : %s\n", OBJ_nid2sn(mdtype));
|
||||||
|
print_hash("Current message digest ", "", mdbuf, mdlen);
|
||||||
|
print_hash("Calculated message digest ", mdok ? "\n" : " MISMATCH!!!\n", cmdbuf, mdlen);
|
||||||
|
return mdok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
|
* [returns] pointer to SpcSpOpusInfo structure
|
||||||
|
*/
|
||||||
|
static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
SpcSpOpusInfo *info = SpcSpOpusInfo_new();
|
||||||
|
|
||||||
|
if (ctx->options->desc) {
|
||||||
|
info->programName = SpcString_new();
|
||||||
|
info->programName->type = 1;
|
||||||
|
info->programName->value.ascii = ASN1_IA5STRING_new();
|
||||||
|
ASN1_STRING_set((ASN1_STRING *)info->programName->value.ascii,
|
||||||
|
ctx->options->desc, (int)strlen(ctx->options->desc));
|
||||||
|
}
|
||||||
|
if (ctx->options->url) {
|
||||||
|
info->moreInfo = SpcLink_new();
|
||||||
|
info->moreInfo->type = 0;
|
||||||
|
info->moreInfo->value.url = ASN1_IA5STRING_new();
|
||||||
|
ASN1_STRING_set((ASN1_STRING *)info->moreInfo->value.url,
|
||||||
|
ctx->options->url, (int)strlen(ctx->options->url));
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [out] blob: SpcIndirectDataContent data
|
||||||
|
* [out] len: SpcIndirectDataContent data length
|
||||||
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
u_char *p = NULL;
|
||||||
|
int mdtype, hashlen, l = 0;
|
||||||
|
void *hash;
|
||||||
|
SpcIndirectDataContent *idc = SpcIndirectDataContent_new();
|
||||||
|
|
||||||
|
if (!ctx->format->data_blob_get || !ctx->format->hash_length_get) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->format->md_get) {
|
||||||
|
/* APPX file specific - use a hash algorithm specified in the AppxBlockMap.xml file */
|
||||||
|
mdtype = EVP_MD_nid(ctx->format->md_get(ctx));
|
||||||
|
} else {
|
||||||
|
mdtype = EVP_MD_nid(ctx->options->md);
|
||||||
|
}
|
||||||
|
idc->data->value = ASN1_TYPE_new();
|
||||||
|
idc->data->value->type = V_ASN1_SEQUENCE;
|
||||||
|
idc->data->value->value.sequence = ASN1_STRING_new();
|
||||||
|
idc->data->type = ctx->format->data_blob_get(&p, &l, ctx);
|
||||||
|
idc->data->value->value.sequence->data = p;
|
||||||
|
idc->data->value->value.sequence->length = l;
|
||||||
|
idc->messageDigest->digestAlgorithm->algorithm = OBJ_nid2obj(mdtype);
|
||||||
|
idc->messageDigest->digestAlgorithm->parameters = ASN1_TYPE_new();
|
||||||
|
idc->messageDigest->digestAlgorithm->parameters->type = V_ASN1_NULL;
|
||||||
|
|
||||||
|
hashlen = ctx->format->hash_length_get(ctx);
|
||||||
|
hash = OPENSSL_zalloc((size_t)hashlen);
|
||||||
|
ASN1_OCTET_STRING_set(idc->messageDigest->digest, hash, hashlen);
|
||||||
|
OPENSSL_free(hash);
|
||||||
|
|
||||||
|
*len = i2d_SpcIndirectDataContent(idc, NULL);
|
||||||
|
*blob = OPENSSL_malloc((size_t)*len);
|
||||||
|
p = *blob;
|
||||||
|
i2d_SpcIndirectDataContent(idc, &p);
|
||||||
|
SpcIndirectDataContent_free(idc);
|
||||||
|
*len -= hashlen;
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
SpcSpOpusInfo *opus;
|
||||||
|
ASN1_STRING *astr;
|
||||||
|
int len;
|
||||||
|
u_char *p = NULL;
|
||||||
|
|
||||||
|
opus = spc_sp_opus_info_create(ctx);
|
||||||
|
if ((len = i2d_SpcSpOpusInfo(opus, NULL)) <= 0
|
||||||
|
|| (p = OPENSSL_malloc((size_t)len)) == NULL) {
|
||||||
|
SpcSpOpusInfo_free(opus);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
i2d_SpcSpOpusInfo(opus, &p);
|
||||||
|
p -= len;
|
||||||
|
astr = ASN1_STRING_new();
|
||||||
|
ASN1_STRING_set(astr, p, len);
|
||||||
|
OPENSSL_free(p);
|
||||||
|
SpcSpOpusInfo_free(opus);
|
||||||
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(SPC_SP_OPUS_INFO_OBJID),
|
||||||
|
V_ASN1_SEQUENCE, astr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a custom, non-trusted time to the PKCS7 structure to prevent OpenSSL
|
||||||
|
* adding the _current_ time. This allows to create a deterministic signature
|
||||||
|
* when no trusted timestamp server was specified, making osslsigncode
|
||||||
|
* behaviour closer to signtool.exe (which doesn't include any non-trusted
|
||||||
|
* time in this case.)
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->options->time == INVALID_TIME) /* -time option was not specified */
|
||||||
|
return 1; /* SUCCESS */
|
||||||
|
return PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, V_ASN1_UTCTIME,
|
||||||
|
ASN1_TIME_adj(NULL, ctx->options->time, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
static const u_char purpose_ind[] = {
|
||||||
|
0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
|
||||||
|
0x01, 0x82, 0x37, 0x02, 0x01, 0x15
|
||||||
|
};
|
||||||
|
static const u_char purpose_comm[] = {
|
||||||
|
0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
|
||||||
|
0x01, 0x82, 0x37, 0x02, 0x01, 0x16
|
||||||
|
};
|
||||||
|
ASN1_STRING *purpose = ASN1_STRING_new();
|
||||||
|
|
||||||
|
if (ctx->options->comm) {
|
||||||
|
ASN1_STRING_set(purpose, purpose_comm, sizeof purpose_comm);
|
||||||
|
} else {
|
||||||
|
ASN1_STRING_set(purpose, purpose_ind, sizeof purpose_ind);
|
||||||
|
}
|
||||||
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(SPC_STATEMENT_TYPE_OBJID),
|
||||||
|
V_ASN1_SEQUENCE, purpose);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_sequence_number(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
ASN1_INTEGER *number = ASN1_INTEGER_new();
|
||||||
|
|
||||||
|
if (!number)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!ASN1_INTEGER_set(number, ctx->options->nested_number + 1)) {
|
||||||
|
ASN1_INTEGER_free(number);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(PKCS9_SEQUENCE_NUMBER),
|
||||||
|
V_ASN1_INTEGER, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create certificate chain sorted in ascending order by their DER encoding.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] signer: signer's certificate number in the certificate chain
|
||||||
|
* [returns] sorted certificate chain
|
||||||
|
*/
|
||||||
|
static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
STACK_OF(X509) *chain = sk_X509_new(X509_compare);
|
||||||
|
|
||||||
|
/* add the signer's certificate */
|
||||||
|
if (ctx->options->cert != NULL && !sk_X509_push(chain, ctx->options->cert)) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* add the certificate chain */
|
||||||
|
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
|
||||||
|
if (i == signer)
|
||||||
|
continue;
|
||||||
|
if (!sk_X509_push(chain, sk_X509_value(ctx->options->certs, i))) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* add all cross certificates */
|
||||||
|
if (ctx->options->xcerts) {
|
||||||
|
for (i=0; i<sk_X509_num(ctx->options->xcerts); i++) {
|
||||||
|
if (!sk_X509_push(chain, sk_X509_value(ctx->options->xcerts, i))) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* sort certificate chain using the supplied comparison function */
|
||||||
|
sk_X509_sort(chain);
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* X.690-compliant certificate comparison function
|
||||||
|
* Windows requires catalog files to use PKCS#7
|
||||||
|
* content ordering specified in X.690 section 11.6
|
||||||
|
* https://support.microsoft.com/en-us/topic/october-13-2020-kb4580358-security-only-update-d3f6eb3c-d7c4-a9cb-0de6-759386bf7113
|
||||||
|
* This algorithm is different from X509_cmp()
|
||||||
|
* [in] a_ptr, b_ptr: pointers to X509 certificates
|
||||||
|
* [returns] certificates order
|
||||||
|
*/
|
||||||
|
static int X509_compare(const X509 *const *a, const X509 *const *b)
|
||||||
|
{
|
||||||
|
u_char *a_data, *b_data, *a_tmp, *b_tmp;
|
||||||
|
size_t a_len, b_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
a_len = (size_t)i2d_X509(*a, NULL);
|
||||||
|
a_tmp = a_data = OPENSSL_malloc(a_len);
|
||||||
|
i2d_X509(*a, &a_tmp);
|
||||||
|
|
||||||
|
b_len = (size_t)i2d_X509(*b, NULL);
|
||||||
|
b_tmp = b_data = OPENSSL_malloc(b_len);
|
||||||
|
i2d_X509(*b, &b_tmp);
|
||||||
|
|
||||||
|
ret = memcmp(a_data, b_data, MIN(a_len, b_len));
|
||||||
|
OPENSSL_free(a_data);
|
||||||
|
OPENSSL_free(b_data);
|
||||||
|
|
||||||
|
if (ret == 0 && a_len != b_len) /* identical up to the length of the shorter DER */
|
||||||
|
ret = a_len < b_len ? -1 : 1; /* shorter is smaller */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
37
helpers.h
Normal file
37
helpers.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* osslsigncode support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Common functions */
|
||||||
|
uint32_t get_file_size(const char *infile);
|
||||||
|
char *map_file(const char *infile, const size_t size);
|
||||||
|
void unmap_file(char *indata, const size_t size);
|
||||||
|
PKCS7 *pkcs7_read_data(char *indata, uint32_t size);
|
||||||
|
int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx);
|
||||||
|
int add_indirect_data_object(PKCS7 *p7);
|
||||||
|
int sign_spc_indirect_data_content(PKCS7 *p7, ASN1_OCTET_STRING *content);
|
||||||
|
PKCS7 *pkcs7_set_content(ASN1_OCTET_STRING *content);
|
||||||
|
ASN1_OCTET_STRING *spc_indirect_data_content_get(BIO *hash, FILE_FORMAT_CTX *ctx);
|
||||||
|
int pkcs7_sign_content(PKCS7 *p7, const u_char *data, int len);
|
||||||
|
int asn1_simple_hdr_len(const u_char *p, int len);
|
||||||
|
int bio_hash_data(BIO *hash, char *indata, size_t idx, size_t fileend);
|
||||||
|
void print_hash(const char *descript1, const char *descript2, const u_char *hashbuf, int length);
|
||||||
|
int is_content_type(PKCS7 *p7, const char *objid);
|
||||||
|
MsCtlContent *ms_ctl_content_get(PKCS7 *p7);
|
||||||
|
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
|
||||||
|
SpcLink *spc_link_obsolete_get(void);
|
||||||
|
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
238
msi.h
238
msi.h
@ -1,238 +0,0 @@
|
|||||||
/*
|
|
||||||
* MSI file support library
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
|
||||||
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
|
||||||
*
|
|
||||||
* Reference specifications:
|
|
||||||
* http://en.wikipedia.org/wiki/Compound_File_Binary_Format
|
|
||||||
* https://msdn.microsoft.com/en-us/library/dd942138.aspx
|
|
||||||
* https://github.com/microsoft/compoundfilereader
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <openssl/safestack.h>
|
|
||||||
#include <openssl/bio.h>
|
|
||||||
#include <openssl/crypto.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
|
|
||||||
#define MAXREGSECT 0xfffffffa /* maximum regular sector number */
|
|
||||||
#define DIFSECT 0xfffffffc /* specifies a DIFAT sector in the FAT */
|
|
||||||
#define FATSECT 0xfffffffd /* specifies a FAT sector in the FAT */
|
|
||||||
#define ENDOFCHAIN 0xfffffffe /* end of a linked chain of sectors */
|
|
||||||
#define NOSTREAM 0xffffffff /* terminator or empty pointer */
|
|
||||||
#define FREESECT 0xffffffff /* empty unallocated free sectors */
|
|
||||||
|
|
||||||
#define DIR_UNKNOWN 0
|
|
||||||
#define DIR_STORAGE 1
|
|
||||||
#define DIR_STREAM 2
|
|
||||||
#define DIR_ROOT 5
|
|
||||||
|
|
||||||
#define RED_COLOR 0
|
|
||||||
#define BLACK_COLOR 1
|
|
||||||
|
|
||||||
#define DIFAT_IN_HEADER 109
|
|
||||||
#define MINI_STREAM_CUTOFF_SIZE 0x00001000 /* 4096 bytes */
|
|
||||||
#define HEADER_SIZE 0x200 /* 512 bytes, independent of sector size */
|
|
||||||
#define MAX_SECTOR_SIZE 0x1000 /* 4096 bytes */
|
|
||||||
|
|
||||||
#define HEADER_SIGNATURE 0x00 /* 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 */
|
|
||||||
#define HEADER_CLSID 0x08 /* reserved and unused */
|
|
||||||
#define HEADER_MINOR_VER 0x18 /* SHOULD be set to 0x003E */
|
|
||||||
#define HEADER_MAJOR_VER 0x1a /* MUST be set to either 0x0003 (version 3) or 0x0004 (version 4) */
|
|
||||||
#define HEADER_BYTE_ORDER 0x1c /* 0xfe 0xff == Intel Little Endian */
|
|
||||||
#define HEADER_SECTOR_SHIFT 0x1e /* MUST be set to 0x0009, or 0x000c */
|
|
||||||
#define HEADER_MINI_SECTOR_SHIFT 0x20 /* MUST be set to 0x0006 */
|
|
||||||
#define RESERVED 0x22 /* reserved and unused */
|
|
||||||
#define HEADER_DIR_SECTORS_NUM 0x28
|
|
||||||
#define HEADER_FAT_SECTORS_NUM 0x2c
|
|
||||||
#define HEADER_DIR_SECTOR_LOC 0x30
|
|
||||||
#define HEADER_TRANSACTION 0x34
|
|
||||||
#define HEADER_MINI_STREAM_CUTOFF 0x38 /* 4096 bytes */
|
|
||||||
#define HEADER_MINI_FAT_SECTOR_LOC 0x3c
|
|
||||||
#define HEADER_MINI_FAT_SECTORS_NUM 0x40
|
|
||||||
#define HEADER_DIFAT_SECTOR_LOC 0x44
|
|
||||||
#define HEADER_DIFAT_SECTORS_NUM 0x48
|
|
||||||
#define HEADER_DIFAT 0x4c
|
|
||||||
|
|
||||||
#define DIRENT_SIZE 0x80 /* 128 bytes */
|
|
||||||
#define DIRENT_MAX_NAME_SIZE 0x40 /* 64 bytes */
|
|
||||||
|
|
||||||
#define DIRENT_NAME 0x00
|
|
||||||
#define DIRENT_NAME_LEN 0x40 /* length in bytes incl 0 terminator */
|
|
||||||
#define DIRENT_TYPE 0x42
|
|
||||||
#define DIRENT_COLOUR 0x43
|
|
||||||
#define DIRENT_LEFT_SIBLING_ID 0x44
|
|
||||||
#define DIRENT_RIGHT_SIBLING_ID 0x48
|
|
||||||
#define DIRENT_CHILD_ID 0x4c
|
|
||||||
#define DIRENT_CLSID 0x50
|
|
||||||
#define DIRENT_STATE_BITS 0x60
|
|
||||||
#define DIRENT_CREATE_TIME 0x64
|
|
||||||
#define DIRENT_MODIFY_TIME 0x6c
|
|
||||||
#define DIRENT_START_SECTOR_LOC 0x74
|
|
||||||
#define DIRENT_FILE_SIZE 0x78
|
|
||||||
|
|
||||||
#define GET_UINT8_LE(p) ((const u_char *)(p))[0]
|
|
||||||
|
|
||||||
#define GET_UINT16_LE(p) (uint16_t)(((const u_char *)(p))[0] | \
|
|
||||||
(((const u_char *)(p))[1] << 8))
|
|
||||||
|
|
||||||
#define GET_UINT32_LE(p) (uint32_t)(((const u_char *)(p))[0] | \
|
|
||||||
(((const u_char *)(p))[1] << 8) | \
|
|
||||||
(((const u_char *)(p))[2] << 16) | \
|
|
||||||
(((const u_char *)(p))[3] << 24))
|
|
||||||
|
|
||||||
#define PUT_UINT8_LE(i, p) ((u_char *)(p))[0] = (u_char)((i) & 0xff);
|
|
||||||
|
|
||||||
#define PUT_UINT16_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
|
||||||
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff)
|
|
||||||
|
|
||||||
#define PUT_UINT32_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
|
||||||
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff); \
|
|
||||||
((u_char *)(p))[2] = (u_char)(((i) >> 16) & 0xff); \
|
|
||||||
((u_char *)(p))[3] = (u_char)(((i) >> 24) & 0xff)
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SIZE_64K 65536 /* 2^16 */
|
|
||||||
#define SIZE_16M 16777216 /* 2^24 */
|
|
||||||
|
|
||||||
typedef unsigned char u_char;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_char signature[8]; /* 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 */
|
|
||||||
u_char unused_clsid[16]; /* reserved and unused */
|
|
||||||
uint16_t minorVersion;
|
|
||||||
uint16_t majorVersion;
|
|
||||||
uint16_t byteOrder;
|
|
||||||
uint16_t sectorShift; /* power of 2 */
|
|
||||||
uint16_t miniSectorShift; /* power of 2 */
|
|
||||||
u_char reserved[6]; /* reserved and unused */
|
|
||||||
uint32_t numDirectorySector;
|
|
||||||
uint32_t numFATSector;
|
|
||||||
uint32_t firstDirectorySectorLocation;
|
|
||||||
uint32_t transactionSignatureNumber; /* reserved */
|
|
||||||
uint32_t miniStreamCutoffSize;
|
|
||||||
uint32_t firstMiniFATSectorLocation;
|
|
||||||
uint32_t numMiniFATSector;
|
|
||||||
uint32_t firstDIFATSectorLocation;
|
|
||||||
uint32_t numDIFATSector;
|
|
||||||
uint32_t headerDIFAT[DIFAT_IN_HEADER];
|
|
||||||
} MSI_FILE_HDR;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_char name[DIRENT_MAX_NAME_SIZE];
|
|
||||||
uint16_t nameLen;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t colorFlag;
|
|
||||||
uint32_t leftSiblingID;
|
|
||||||
uint32_t rightSiblingID;
|
|
||||||
uint32_t childID;
|
|
||||||
u_char clsid[16];
|
|
||||||
u_char stateBits[4];
|
|
||||||
u_char creationTime[8];
|
|
||||||
u_char modifiedTime[8];
|
|
||||||
uint32_t startSectorLocation;
|
|
||||||
u_char size[8];
|
|
||||||
} MSI_ENTRY;
|
|
||||||
|
|
||||||
typedef struct msi_dirent_struct {
|
|
||||||
u_char name[DIRENT_MAX_NAME_SIZE];
|
|
||||||
uint16_t nameLen;
|
|
||||||
uint8_t type;
|
|
||||||
MSI_ENTRY *entry;
|
|
||||||
STACK_OF(MSI_DIRENT) *children;
|
|
||||||
struct msi_dirent_struct *next; /* for cycle detection */
|
|
||||||
} MSI_DIRENT;
|
|
||||||
|
|
||||||
DEFINE_STACK_OF(MSI_DIRENT)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const u_char *m_buffer;
|
|
||||||
uint32_t m_bufferLen;
|
|
||||||
MSI_FILE_HDR *m_hdr;
|
|
||||||
uint32_t m_sectorSize;
|
|
||||||
uint32_t m_minisectorSize;
|
|
||||||
uint32_t m_miniStreamStartSector;
|
|
||||||
} MSI_FILE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *header;
|
|
||||||
char *ministream;
|
|
||||||
char *minifat;
|
|
||||||
char *fat;
|
|
||||||
uint32_t dirtreeLen;
|
|
||||||
uint32_t miniStreamLen;
|
|
||||||
uint32_t minifatLen;
|
|
||||||
uint32_t fatLen;
|
|
||||||
uint32_t ministreamsMemallocCount;
|
|
||||||
uint32_t minifatMemallocCount;
|
|
||||||
uint32_t fatMemallocCount;
|
|
||||||
uint32_t dirtreeSectorsCount;
|
|
||||||
uint32_t minifatSectorsCount;
|
|
||||||
uint32_t fatSectorsCount;
|
|
||||||
uint32_t miniSectorNum;
|
|
||||||
uint32_t sectorNum;
|
|
||||||
uint32_t sectorSize;
|
|
||||||
} MSI_OUT;
|
|
||||||
|
|
||||||
static const u_char msi_magic[] = {
|
|
||||||
0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char digital_signature[] = {
|
|
||||||
0x05, 0x00, 0x44, 0x00, 0x69, 0x00, 0x67, 0x00,
|
|
||||||
0x69, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6C, 0x00,
|
|
||||||
0x53, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6E, 0x00,
|
|
||||||
0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00,
|
|
||||||
0x65, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char digital_signature_ex[] = {
|
|
||||||
0x05, 0x00, 0x4D, 0x00, 0x73, 0x00, 0x69, 0x00,
|
|
||||||
0x44, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00,
|
|
||||||
0x74, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x53, 0x00,
|
|
||||||
0x69, 0x00, 0x67, 0x00, 0x6E, 0x00, 0x61, 0x00,
|
|
||||||
0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00,
|
|
||||||
0x45, 0x00, 0x78, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char msi_root_entry[] = {
|
|
||||||
0x52, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x74, 0x00,
|
|
||||||
0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x74, 0x00,
|
|
||||||
0x72, 0x00, 0x79, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char msi_zeroes[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer, uint32_t len);
|
|
||||||
MSI_FILE *msi_file_new(char *buffer, uint32_t len);
|
|
||||||
void msi_file_free(MSI_FILE *msi);
|
|
||||||
MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi);
|
|
||||||
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret);
|
|
||||||
MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
|
|
||||||
void msi_dirent_free(MSI_DIRENT *dirent);
|
|
||||||
int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
|
|
||||||
int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root);
|
|
||||||
int msi_calc_digest(char *indata, int mdtype, u_char *mdbuf, uint32_t fileend);
|
|
||||||
int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLen);
|
|
||||||
int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p, uint32_t len,
|
|
||||||
u_char *p_msiex, uint32_t len_msiex, BIO *outdata);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Local Variables:
|
|
||||||
c-basic-offset: 4
|
|
||||||
tab-width: 4
|
|
||||||
indent-tabs-mode: t
|
|
||||||
End:
|
|
||||||
|
|
||||||
vim: set ts=4 noexpandtab:
|
|
||||||
*/
|
|
8669
osslsigncode.c
8669
osslsigncode.c
File diff suppressed because it is too large
Load Diff
556
osslsigncode.h
Normal file
556
osslsigncode.h
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OPENSSL_API_COMPAT 0x10100000L
|
||||||
|
#define OPENSSL_NO_DEPRECATED
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define HAVE_WINDOWS_H
|
||||||
|
#endif /* _MSC_VER || __MINGW32__ */
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#define NOCRYPT
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif /* HAVE_WINDOWS_H */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif /* HAVE_SYS_MMAN_H */
|
||||||
|
#ifdef HAVE_TERMIOS_H
|
||||||
|
#include <termios.h>
|
||||||
|
#endif /* HAVE_TERMIOS_H */
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <openssl/asn1t.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/cms.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#endif /* OPENSSL_NO_ENGINE */
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/objects.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/pkcs7.h>
|
||||||
|
#include <openssl/pkcs12.h>
|
||||||
|
#if OPENSSL_VERSION_NUMBER>=0x30000000L
|
||||||
|
#include <openssl/provider.h>
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/safestack.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/ts.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/x509v3.h> /* X509_PURPOSE */
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#ifndef SOCKET
|
||||||
|
#define SOCKET UINT_PTR
|
||||||
|
#endif /* SOCKET */
|
||||||
|
#endif /* __CYGWIN__ */
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#endif /* ENABLE_CURL */
|
||||||
|
|
||||||
|
/* Request nonce length, in bits (must be a multiple of 8). */
|
||||||
|
#define NONCE_LENGTH 64
|
||||||
|
#define MAX_TS_SERVERS 256
|
||||||
|
|
||||||
|
#if defined (HAVE_TERMIOS_H) || defined (HAVE_GETPASS)
|
||||||
|
#define PROVIDE_ASKPASS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* not WIN32, because strcasecmp exists in MinGW */
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define remove_file(filename) _unlink(filename)
|
||||||
|
#else
|
||||||
|
#define remove_file(filename) unlink(filename)
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
#define GET_UINT8_LE(p) ((const u_char *)(p))[0]
|
||||||
|
|
||||||
|
#define GET_UINT16_LE(p) (uint16_t)(((const u_char *)(p))[0] | \
|
||||||
|
(((const u_char *)(p))[1] << 8))
|
||||||
|
|
||||||
|
#define GET_UINT32_LE(p) (uint32_t)(((const u_char *)(p))[0] | \
|
||||||
|
(((const u_char *)(p))[1] << 8) | \
|
||||||
|
(((const u_char *)(p))[2] << 16) | \
|
||||||
|
(((const u_char *)(p))[3] << 24))
|
||||||
|
|
||||||
|
#define PUT_UINT8_LE(i, p) ((u_char *)(p))[0] = (u_char)((i) & 0xff);
|
||||||
|
|
||||||
|
#define PUT_UINT16_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
||||||
|
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff)
|
||||||
|
|
||||||
|
#define PUT_UINT32_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
||||||
|
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff); \
|
||||||
|
((u_char *)(p))[2] = (u_char)(((i) >> 16) & 0xff); \
|
||||||
|
((u_char *)(p))[3] = (u_char)(((i) >> 24) & 0xff)
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIZE_64K 65536 /* 2^16 */
|
||||||
|
#define SIZE_16M 16777216 /* 2^24 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro names:
|
||||||
|
* linux: __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
|
||||||
|
* BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
|
||||||
|
* bsd: _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
|
||||||
|
* BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
|
||||||
|
* solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BYTE_ORDER
|
||||||
|
#define LITTLE_ENDIAN 1234
|
||||||
|
#define BIG_ENDIAN 4321
|
||||||
|
#define BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
#endif /* BYTE_ORDER */
|
||||||
|
|
||||||
|
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
|
||||||
|
#error "Cannot determine the endian-ness of this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOWORD
|
||||||
|
#define LOWORD(x) ((x) & 0xFFFF)
|
||||||
|
#endif /* LOWORD */
|
||||||
|
#ifndef HIWORD
|
||||||
|
#define HIWORD(x) (((x) >> 16) & 0xFFFF)
|
||||||
|
#endif /* HIWORD */
|
||||||
|
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
#define LE_UINT16(x) ((((x) >> 8) & 0x00FF) | \
|
||||||
|
(((x) << 8) & 0xFF00))
|
||||||
|
#define LE_UINT32(x) (((x) >> 24) | \
|
||||||
|
(((x) & 0x00FF0000) >> 8) | \
|
||||||
|
(((x) & 0x0000FF00) << 8) | \
|
||||||
|
((x) << 24))
|
||||||
|
#else
|
||||||
|
#define LE_UINT16(x) (x)
|
||||||
|
#define LE_UINT32(x) (x)
|
||||||
|
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a) < (b) ? a : b)
|
||||||
|
#define INVALID_TIME ((time_t)-1)
|
||||||
|
|
||||||
|
/* Microsoft OID Authenticode */
|
||||||
|
#define SPC_INDIRECT_DATA_OBJID "1.3.6.1.4.1.311.2.1.4"
|
||||||
|
#define SPC_STATEMENT_TYPE_OBJID "1.3.6.1.4.1.311.2.1.11"
|
||||||
|
#define SPC_SP_OPUS_INFO_OBJID "1.3.6.1.4.1.311.2.1.12"
|
||||||
|
#define SPC_PE_IMAGE_DATA_OBJID "1.3.6.1.4.1.311.2.1.15"
|
||||||
|
#define SPC_CAB_DATA_OBJID "1.3.6.1.4.1.311.2.1.25"
|
||||||
|
#define SPC_SIPINFO_OBJID "1.3.6.1.4.1.311.2.1.30"
|
||||||
|
#define SPC_PE_IMAGE_PAGE_HASHES_V1 "1.3.6.1.4.1.311.2.3.1" /* SHA1 */
|
||||||
|
#define SPC_PE_IMAGE_PAGE_HASHES_V2 "1.3.6.1.4.1.311.2.3.2" /* SHA256 */
|
||||||
|
#define SPC_NESTED_SIGNATURE_OBJID "1.3.6.1.4.1.311.2.4.1"
|
||||||
|
/* Microsoft OID Time Stamping */
|
||||||
|
#define SPC_TIME_STAMP_REQUEST_OBJID "1.3.6.1.4.1.311.3.2.1"
|
||||||
|
#define SPC_RFC3161_OBJID "1.3.6.1.4.1.311.3.3.1"
|
||||||
|
/* Microsoft OID Crypto 2.0 */
|
||||||
|
#define MS_CTL_OBJID "1.3.6.1.4.1.311.10.1"
|
||||||
|
/* Microsoft OID Catalog */
|
||||||
|
#define CAT_NAMEVALUE_OBJID "1.3.6.1.4.1.311.12.2.1"
|
||||||
|
/* Microsoft OID Microsoft_Java */
|
||||||
|
#define MS_JAVA_SOMETHING "1.3.6.1.4.1.311.15.1"
|
||||||
|
|
||||||
|
#define SPC_UNAUTHENTICATED_DATA_BLOB_OBJID "1.3.6.1.4.1.42921.1.2.1"
|
||||||
|
|
||||||
|
/* Public Key Cryptography Standards PKCS#9 */
|
||||||
|
#define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
|
||||||
|
#define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5"
|
||||||
|
#define PKCS9_COUNTER_SIGNATURE "1.2.840.113549.1.9.6"
|
||||||
|
#define PKCS9_SEQUENCE_NUMBER "1.2.840.113549.1.9.25.4"
|
||||||
|
|
||||||
|
/* WIN_CERTIFICATE structure declared in Wintrust.h */
|
||||||
|
#define WIN_CERT_REVISION_2_0 0x0200
|
||||||
|
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FLAG_PREV_CABINET is set if the cabinet file is not the first in a set
|
||||||
|
* of cabinet files. When this bit is set, the szCabinetPrev and szDiskPrev
|
||||||
|
* fields are present in this CFHEADER.
|
||||||
|
*/
|
||||||
|
#define FLAG_PREV_CABINET 0x0001
|
||||||
|
/*
|
||||||
|
* FLAG_NEXT_CABINET is set if the cabinet file is not the last in a set of
|
||||||
|
* cabinet files. When this bit is set, the szCabinetNext and szDiskNext
|
||||||
|
* fields are present in this CFHEADER.
|
||||||
|
*/
|
||||||
|
#define FLAG_NEXT_CABINET 0x0002
|
||||||
|
/*
|
||||||
|
* FLAG_RESERVE_PRESENT is set if the cabinet file contains any reserved
|
||||||
|
* fields. When this bit is set, the cbCFHeader, cbCFFolder, and cbCFData
|
||||||
|
* fields are present in this CFHEADER.
|
||||||
|
*/
|
||||||
|
#define FLAG_RESERVE_PRESENT 0x0004
|
||||||
|
|
||||||
|
#define DO_EXIT_0(x) { fprintf(stderr, x); goto err_cleanup; }
|
||||||
|
#define DO_EXIT_1(x, y) { fprintf(stderr, x, y); goto err_cleanup; }
|
||||||
|
#define DO_EXIT_2(x, y, z) { fprintf(stderr, x, y, z); goto err_cleanup; }
|
||||||
|
|
||||||
|
/* Default policy if request did not specify it. */
|
||||||
|
#define TSA_POLICY1 "1.2.3.4.1"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD_SIGN,
|
||||||
|
CMD_EXTRACT,
|
||||||
|
CMD_EXTRACT_DATA,
|
||||||
|
CMD_REMOVE,
|
||||||
|
CMD_VERIFY,
|
||||||
|
CMD_ADD,
|
||||||
|
CMD_ATTACH,
|
||||||
|
CMD_HELP,
|
||||||
|
CMD_DEFAULT
|
||||||
|
} cmd_type_t;
|
||||||
|
|
||||||
|
typedef unsigned char u_char;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *infile;
|
||||||
|
char *outfile;
|
||||||
|
char *sigfile;
|
||||||
|
char *certfile;
|
||||||
|
char *xcertfile;
|
||||||
|
char *keyfile;
|
||||||
|
char *pvkfile;
|
||||||
|
char *pkcs12file;
|
||||||
|
int output_pkcs7;
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
char *p11engine;
|
||||||
|
char *p11module;
|
||||||
|
char *p11cert;
|
||||||
|
int login;
|
||||||
|
#endif /* OPENSSL_NO_ENGINE */
|
||||||
|
int askpass;
|
||||||
|
char *readpass;
|
||||||
|
char *pass;
|
||||||
|
int comm;
|
||||||
|
int pagehash;
|
||||||
|
char *desc;
|
||||||
|
const EVP_MD *md;
|
||||||
|
char *url;
|
||||||
|
time_t time;
|
||||||
|
char *turl[MAX_TS_SERVERS];
|
||||||
|
int nturl;
|
||||||
|
char *tsurl[MAX_TS_SERVERS];
|
||||||
|
int ntsurl;
|
||||||
|
char *proxy;
|
||||||
|
int noverifypeer;
|
||||||
|
int addBlob;
|
||||||
|
int nest;
|
||||||
|
int index;
|
||||||
|
int ignore_timestamp;
|
||||||
|
int ignore_cdp;
|
||||||
|
int ignore_crl;
|
||||||
|
int verbose;
|
||||||
|
int add_msi_dse;
|
||||||
|
char *catalog;
|
||||||
|
char *cafile;
|
||||||
|
char *crlfile;
|
||||||
|
char *https_cafile;
|
||||||
|
char *https_crlfile;
|
||||||
|
char *tsa_cafile;
|
||||||
|
char *tsa_crlfile;
|
||||||
|
char *leafhash;
|
||||||
|
int jp;
|
||||||
|
#if OPENSSL_VERSION_NUMBER>=0x30000000L
|
||||||
|
int legacy;
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
X509 *cert;
|
||||||
|
STACK_OF(X509) *certs;
|
||||||
|
STACK_OF(X509) *xcerts;
|
||||||
|
STACK_OF(X509_CRL) *crls;
|
||||||
|
cmd_type_t cmd;
|
||||||
|
char *indata;
|
||||||
|
char *tsa_certfile;
|
||||||
|
char *tsa_keyfile;
|
||||||
|
time_t tsa_time;
|
||||||
|
int nested_number;
|
||||||
|
} GLOBAL_OPTIONS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ASN.1 definitions (more or less from official MS Authenticode docs)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int type;
|
||||||
|
union {
|
||||||
|
ASN1_BMPSTRING *unicode;
|
||||||
|
ASN1_IA5STRING *ascii;
|
||||||
|
} value;
|
||||||
|
} SpcString;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcString)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OCTET_STRING *classId;
|
||||||
|
ASN1_OCTET_STRING *serializedData;
|
||||||
|
} SpcSerializedObject;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcSerializedObject)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int type;
|
||||||
|
union {
|
||||||
|
ASN1_IA5STRING *url;
|
||||||
|
SpcSerializedObject *moniker;
|
||||||
|
SpcString *file;
|
||||||
|
} value;
|
||||||
|
} SpcLink;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcLink)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpcString *programName;
|
||||||
|
SpcLink *moreInfo;
|
||||||
|
} SpcSpOpusInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcSpOpusInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *a;
|
||||||
|
ASN1_OCTET_STRING *string;
|
||||||
|
ASN1_INTEGER *b;
|
||||||
|
ASN1_INTEGER *c;
|
||||||
|
ASN1_INTEGER *d;
|
||||||
|
ASN1_INTEGER *e;
|
||||||
|
ASN1_INTEGER *f;
|
||||||
|
} SpcSipInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcSipInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
ASN1_TYPE *value;
|
||||||
|
} SpcAttributeTypeAndOptionalValue;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcAttributeTypeAndOptionalValue)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *algorithm;
|
||||||
|
ASN1_TYPE *parameters;
|
||||||
|
} AlgorithmIdentifier;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(AlgorithmIdentifier)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AlgorithmIdentifier *digestAlgorithm;
|
||||||
|
ASN1_OCTET_STRING *digest;
|
||||||
|
} DigestInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(DigestInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpcAttributeTypeAndOptionalValue *data;
|
||||||
|
DigestInfo *messageDigest;
|
||||||
|
} SpcIndirectDataContent;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcIndirectDataContent)
|
||||||
|
|
||||||
|
typedef struct CatalogAuthAttr_st {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
ASN1_TYPE *contents;
|
||||||
|
} CatalogAuthAttr;
|
||||||
|
|
||||||
|
DEFINE_STACK_OF(CatalogAuthAttr)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(CatalogAuthAttr)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AlgorithmIdentifier *digestAlgorithm;
|
||||||
|
ASN1_OCTET_STRING *digest;
|
||||||
|
} MessageImprint;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(MessageImprint)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
ASN1_OCTET_STRING *signature;
|
||||||
|
} TimeStampRequestBlob;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampRequestBlob)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
TimeStampRequestBlob *blob;
|
||||||
|
} TimeStampRequest;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampRequest)
|
||||||
|
|
||||||
|
/* RFC3161 Time stamping */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *status;
|
||||||
|
STACK_OF(ASN1_UTF8STRING) *statusString;
|
||||||
|
ASN1_BIT_STRING *failInfo;
|
||||||
|
} PKIStatusInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(PKIStatusInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PKIStatusInfo *status;
|
||||||
|
PKCS7 *token;
|
||||||
|
} TimeStampResp;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampResp)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *version;
|
||||||
|
MessageImprint *messageImprint;
|
||||||
|
ASN1_OBJECT *reqPolicy;
|
||||||
|
ASN1_INTEGER *nonce;
|
||||||
|
ASN1_BOOLEAN certReq;
|
||||||
|
STACK_OF(X509_EXTENSION) *extensions;
|
||||||
|
} TimeStampReq;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampReq)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *seconds;
|
||||||
|
ASN1_INTEGER *millis;
|
||||||
|
ASN1_INTEGER *micros;
|
||||||
|
} TimeStampAccuracy;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampAccuracy)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *version;
|
||||||
|
ASN1_OBJECT *policy_id;
|
||||||
|
MessageImprint *messageImprint;
|
||||||
|
ASN1_INTEGER *serial;
|
||||||
|
ASN1_GENERALIZEDTIME *time;
|
||||||
|
TimeStampAccuracy *accuracy;
|
||||||
|
ASN1_BOOLEAN ordering;
|
||||||
|
ASN1_INTEGER *nonce;
|
||||||
|
GENERAL_NAME *tsa;
|
||||||
|
STACK_OF(X509_EXTENSION) *extensions;
|
||||||
|
} TimeStampToken;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampToken)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OCTET_STRING *digest;
|
||||||
|
STACK_OF(CatalogAuthAttr) *attributes;
|
||||||
|
} CatalogInfo;
|
||||||
|
|
||||||
|
DEFINE_STACK_OF(CatalogInfo)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(CatalogInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 1.3.6.1.4.1.311.12.1.1 MS_CATALOG_LIST */
|
||||||
|
SpcAttributeTypeAndOptionalValue *type;
|
||||||
|
ASN1_OCTET_STRING *identifier;
|
||||||
|
ASN1_UTCTIME *time;
|
||||||
|
/* 1.3.6.1.4.1.311.12.1.2 CatalogVersion = 1
|
||||||
|
* 1.3.6.1.4.1.311.12.1.3 CatalogVersion = 2 */
|
||||||
|
SpcAttributeTypeAndOptionalValue *version;
|
||||||
|
STACK_OF(CatalogInfo) *header_attributes;
|
||||||
|
/* 1.3.6.1.4.1.311.12.2.1 CAT_NAMEVALUE_OBJID */
|
||||||
|
ASN1_TYPE *filename;
|
||||||
|
} MsCtlContent;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(MsCtlContent)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *server;
|
||||||
|
const char *port;
|
||||||
|
int use_proxy;
|
||||||
|
int timeout;
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
} HTTP_TLS_Info;
|
||||||
|
|
||||||
|
typedef struct file_format_st FILE_FORMAT;
|
||||||
|
|
||||||
|
typedef struct script_ctx_st SCRIPT_CTX;
|
||||||
|
typedef struct msi_ctx_st MSI_CTX;
|
||||||
|
typedef struct pe_ctx_st PE_CTX;
|
||||||
|
typedef struct cab_ctx_st CAB_CTX;
|
||||||
|
typedef struct cat_ctx_st CAT_CTX;
|
||||||
|
typedef struct appx_ctx_st APPX_CTX;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FILE_FORMAT *format;
|
||||||
|
GLOBAL_OPTIONS *options;
|
||||||
|
union {
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
|
MSI_CTX *msi_ctx;
|
||||||
|
PE_CTX *pe_ctx;
|
||||||
|
CAB_CTX *cab_ctx;
|
||||||
|
CAT_CTX *cat_ctx;
|
||||||
|
APPX_CTX *appx_ctx;
|
||||||
|
};
|
||||||
|
} FILE_FORMAT_CTX;
|
||||||
|
|
||||||
|
extern FILE_FORMAT file_format_script;
|
||||||
|
extern FILE_FORMAT file_format_msi;
|
||||||
|
extern FILE_FORMAT file_format_pe;
|
||||||
|
extern FILE_FORMAT file_format_cab;
|
||||||
|
extern FILE_FORMAT file_format_cat;
|
||||||
|
extern FILE_FORMAT file_format_appx;
|
||||||
|
|
||||||
|
struct file_format_st {
|
||||||
|
FILE_FORMAT_CTX *(*ctx_new) (GLOBAL_OPTIONS *option, BIO *hash, BIO *outdata);
|
||||||
|
const EVP_MD *(*md_get) (FILE_FORMAT_CTX *ctx);
|
||||||
|
ASN1_OBJECT *(*data_blob_get) (u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
PKCS7 *(*pkcs7_contents_get) (FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
|
int (*hash_length_get) (FILE_FORMAT_CTX *ctx);
|
||||||
|
u_char *(*digest_calc) (FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
|
int (*verify_digests) (FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
|
int (*verify_indirect_data) (FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj);
|
||||||
|
PKCS7 *(*pkcs7_extract) (FILE_FORMAT_CTX *ctx);
|
||||||
|
PKCS7 *(*pkcs7_extract_to_nest) (FILE_FORMAT_CTX *ctx);
|
||||||
|
int (*remove_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
int (*process_data) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
PKCS7 *(*pkcs7_signature_new) (FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
|
int (*append_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
void (*update_data_size) (FILE_FORMAT_CTX *data, BIO *outdata, PKCS7 *p7);
|
||||||
|
void (*bio_free) (BIO *hash, BIO *outdata);
|
||||||
|
void (*ctx_cleanup) (FILE_FORMAT_CTX *ctx);
|
||||||
|
int (*is_detaching_supported) (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
875
script.c
Normal file
875
script.c
Normal file
@ -0,0 +1,875 @@
|
|||||||
|
/*
|
||||||
|
* Script file support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2024 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osslsigncode.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "utf.h"
|
||||||
|
|
||||||
|
typedef enum {comment_hash, comment_xml, comment_c, comment_not_found} comment_style;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *extension;
|
||||||
|
comment_style comment;
|
||||||
|
} SCRIPT_FORMAT;
|
||||||
|
|
||||||
|
const SCRIPT_FORMAT supported_formats[] = {
|
||||||
|
{".ps1", comment_hash},
|
||||||
|
{".ps1xml", comment_xml},
|
||||||
|
{".psc1", comment_xml},
|
||||||
|
{".psd1", comment_hash},
|
||||||
|
{".psm1", comment_hash},
|
||||||
|
{".cdxml", comment_xml},
|
||||||
|
{".mof", comment_c},
|
||||||
|
{NULL, comment_not_found},
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *signature_header = "SIG # Begin signature block";
|
||||||
|
const char *signature_footer = "SIG # End signature block";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *open;
|
||||||
|
const char *close;
|
||||||
|
} SCRIPT_COMMENT;
|
||||||
|
|
||||||
|
const SCRIPT_COMMENT comment_text[] = {
|
||||||
|
[comment_hash] = {"# ", ""},
|
||||||
|
[comment_xml] = {"<!-- ", " -->"},
|
||||||
|
[comment_c] = {"/* ", " */"}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct script_ctx_st {
|
||||||
|
const SCRIPT_COMMENT *comment_text;
|
||||||
|
int utf;
|
||||||
|
uint32_t sigpos;
|
||||||
|
uint32_t fileend;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LINE_MAX_LEN 100
|
||||||
|
|
||||||
|
/* FILE_FORMAT method prototypes */
|
||||||
|
static FILE_FORMAT_CTX *script_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
|
static ASN1_OBJECT *script_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *script_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
|
static int script_hash_length_get(FILE_FORMAT_CTX *ctx);
|
||||||
|
static u_char *script_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
|
static int script_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
|
static PKCS7 *script_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *script_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int script_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static int script_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static PKCS7 *script_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
|
static int script_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
static void script_bio_free(BIO *hash, BIO *outdata);
|
||||||
|
static void script_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int script_is_detaching_supported(void);
|
||||||
|
|
||||||
|
FILE_FORMAT file_format_script = {
|
||||||
|
.ctx_new = script_ctx_new,
|
||||||
|
.data_blob_get = script_spc_sip_info_get,
|
||||||
|
.pkcs7_contents_get = script_pkcs7_contents_get,
|
||||||
|
.hash_length_get = script_hash_length_get,
|
||||||
|
.digest_calc = script_digest_calc,
|
||||||
|
.verify_digests = script_verify_digests,
|
||||||
|
.pkcs7_extract = script_pkcs7_extract,
|
||||||
|
.pkcs7_extract_to_nest = script_pkcs7_extract_to_nest,
|
||||||
|
.remove_pkcs7 = script_remove_pkcs7,
|
||||||
|
.process_data = script_process_data,
|
||||||
|
.pkcs7_signature_new = script_pkcs7_signature_new,
|
||||||
|
.append_pkcs7 = script_append_pkcs7,
|
||||||
|
.bio_free = script_bio_free,
|
||||||
|
.ctx_cleanup = script_ctx_cleanup,
|
||||||
|
.is_detaching_supported = script_is_detaching_supported
|
||||||
|
};
|
||||||
|
|
||||||
|
/* helper functions */
|
||||||
|
static SCRIPT_CTX *script_ctx_get(char *indata, uint32_t filesize, const SCRIPT_COMMENT *comment, int utf);
|
||||||
|
static int write_commented(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *data, size_t length);
|
||||||
|
static int write_in_encoding(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *line, size_t length);
|
||||||
|
static size_t utf8_to_utf16(const char *data, size_t len, uint16_t **out_utf16);
|
||||||
|
static size_t utf16_to_utf8(const uint16_t *data, size_t len, char **out_utf8);
|
||||||
|
static BIO *script_digest_calc_bio(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
|
static int script_digest_convert(BIO *hash, FILE_FORMAT_CTX *ctx, size_t len);
|
||||||
|
static int script_write_bio(BIO *data, char *indata, size_t len);
|
||||||
|
static int script_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return a script file format context.
|
||||||
|
* [in, out] options: structure holds the input data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [in] outdata: outdata file BIO (unused)
|
||||||
|
* [returns] pointer to script file format context
|
||||||
|
*/
|
||||||
|
static FILE_FORMAT_CTX *script_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
FILE_FORMAT_CTX *ctx;
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
|
const SCRIPT_FORMAT *fmt;
|
||||||
|
uint32_t filesize;
|
||||||
|
const uint8_t utf16_bom[] = {0xff, 0xfe};
|
||||||
|
size_t name_len;
|
||||||
|
int utf;
|
||||||
|
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)outdata;
|
||||||
|
|
||||||
|
/* find out whether our format is supported */
|
||||||
|
name_len = strlen(options->infile);
|
||||||
|
for (fmt = supported_formats; fmt->comment != comment_not_found; fmt++) {
|
||||||
|
size_t ext_len = strlen(fmt->extension);
|
||||||
|
if(name_len > ext_len && !strcasecmp(options->infile + name_len - ext_len, fmt->extension))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fmt->comment == comment_not_found)
|
||||||
|
return NULL;
|
||||||
|
printf("Script file format: %s\n", fmt->extension);
|
||||||
|
|
||||||
|
filesize = get_file_size(options->infile);
|
||||||
|
if (filesize == 0)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
|
||||||
|
options->indata = map_file(options->infile, filesize);
|
||||||
|
if (!options->indata) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
utf = memcmp(options->indata, utf16_bom, sizeof utf16_bom) ? 8 : 16;
|
||||||
|
|
||||||
|
/* initialize script context */
|
||||||
|
script_ctx = script_ctx_get(options->indata, filesize, comment_text + fmt->comment, utf);
|
||||||
|
if (!script_ctx) {
|
||||||
|
unmap_file(options->indata, filesize);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize file format context */
|
||||||
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
|
memset(ctx, 0, sizeof(FILE_FORMAT_CTX));
|
||||||
|
ctx->format = &file_format_script;
|
||||||
|
ctx->options = options;
|
||||||
|
ctx->script_ctx = script_ctx;
|
||||||
|
|
||||||
|
if (hash)
|
||||||
|
BIO_push(hash, BIO_new(BIO_s_null()));
|
||||||
|
|
||||||
|
/* FIXME: user interface logic belongs to osslsigncode.c */
|
||||||
|
if (options->pagehash == 1)
|
||||||
|
printf("Warning: -ph option is only valid for PE files\n");
|
||||||
|
if (options->jp >= 0)
|
||||||
|
printf("Warning: -jp option is only valid for CAB files\n");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return SpcSipInfo object.
|
||||||
|
* Subject Interface Package (SIP) is an internal Microsoft API for
|
||||||
|
* transforming arbitrary files into a digestible stream.
|
||||||
|
* These ClassIDs are found in the indirect data section and identify
|
||||||
|
* the type of processor needed to validate the signature.
|
||||||
|
* https://github.com/sassoftware/relic/blob/620d0b75ec67c0158a8a9120950abe04327d922f/lib/authenticode/structs.go#L154
|
||||||
|
* [out] p: SpcSipInfo data
|
||||||
|
* [out] plen: SpcSipInfo data length
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to ASN1_OBJECT structure corresponding to SPC_SIPINFO_OBJID
|
||||||
|
*/
|
||||||
|
static ASN1_OBJECT *script_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
const u_char SpcUUIDSipInfoPs[] = {
|
||||||
|
0x1f, 0xcc, 0x3b, 0x60, 0x59, 0x4b, 0x08, 0x4e,
|
||||||
|
0xb7, 0x24, 0xd2, 0xc6, 0x29, 0x7e, 0xf3, 0x51
|
||||||
|
};
|
||||||
|
ASN1_OBJECT *dtype;
|
||||||
|
SpcSipInfo *si = SpcSipInfo_new();
|
||||||
|
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)ctx;
|
||||||
|
|
||||||
|
ASN1_INTEGER_set(si->a, 65536);
|
||||||
|
ASN1_INTEGER_set(si->b, 0);
|
||||||
|
ASN1_INTEGER_set(si->c, 0);
|
||||||
|
ASN1_INTEGER_set(si->d, 0);
|
||||||
|
ASN1_INTEGER_set(si->e, 0);
|
||||||
|
ASN1_INTEGER_set(si->f, 0);
|
||||||
|
ASN1_OCTET_STRING_set(si->string, SpcUUIDSipInfoPs, sizeof SpcUUIDSipInfoPs);
|
||||||
|
*plen = i2d_SpcSipInfo(si, NULL);
|
||||||
|
*p = OPENSSL_malloc((size_t)*plen);
|
||||||
|
i2d_SpcSipInfo(si, p);
|
||||||
|
*p -= *plen;
|
||||||
|
dtype = OBJ_txt2obj(SPC_SIPINFO_OBJID, 1);
|
||||||
|
SpcSipInfo_free(si);
|
||||||
|
return dtype; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return a data content to be signed.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] hash: message digest BIO
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] data content
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
BIO *bhash;
|
||||||
|
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)hash;
|
||||||
|
|
||||||
|
bhash = script_digest_calc_bio(ctx, md);
|
||||||
|
if (!bhash) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(bhash, ctx);
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return pkcs7_set_content(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int script_hash_length_get(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return EVP_MD_size(ctx->options->md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a simple sha1/sha256 message digest of the MSI file
|
||||||
|
* for use with a catalog file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] pointer to calculated message digest
|
||||||
|
*/
|
||||||
|
static u_char *script_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
u_char *mdbuf;
|
||||||
|
BIO *hash = BIO_new(BIO_f_md());
|
||||||
|
|
||||||
|
if (!BIO_set_md(hash, md)) {
|
||||||
|
fprintf(stderr, "Unable to set the message digest of BIO\n");
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_push(hash, BIO_new(BIO_s_null()));
|
||||||
|
if (!script_write_bio(hash, ctx->options->indata, ctx->script_ctx->fileend)) {
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
mdbuf = OPENSSL_malloc((size_t)EVP_MD_size(md));
|
||||||
|
BIO_gets(hash, (char*)mdbuf, EVP_MD_size(md));
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return mdbuf; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the hash and compare to PKCS#7 signedData.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
int mdtype = -1;
|
||||||
|
u_char mdbuf[EVP_MAX_MD_SIZE];
|
||||||
|
u_char *cmdbuf = NULL;
|
||||||
|
const EVP_MD *md;
|
||||||
|
BIO *bhash;
|
||||||
|
|
||||||
|
/* FIXME: this shared code most likely belongs in osslsigncode.c */
|
||||||
|
if (is_content_type(p7, SPC_INDIRECT_DATA_OBJID)) {
|
||||||
|
ASN1_STRING *content_val = p7->d.sign->contents->d.other->value.sequence;
|
||||||
|
const u_char *p = content_val->data;
|
||||||
|
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||||
|
if (idc) {
|
||||||
|
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||||
|
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||||
|
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||||
|
}
|
||||||
|
SpcIndirectDataContent_free(idc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mdtype == -1) {
|
||||||
|
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
md = EVP_get_digestbynid(mdtype);
|
||||||
|
bhash = script_digest_calc_bio(ctx, md);
|
||||||
|
if (!bhash)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
|
||||||
|
cmdbuf = OPENSSL_malloc((size_t)EVP_MD_size(md));
|
||||||
|
BIO_gets(bhash, (char*)cmdbuf, EVP_MD_size(md));
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
|
||||||
|
if (!compare_digests(mdbuf, cmdbuf, mdtype)) {
|
||||||
|
fprintf(stderr, "Signature verification: failed\n\n");
|
||||||
|
OPENSSL_free(cmdbuf);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(cmdbuf);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
const char *signature_data = ctx->options->indata + ctx->script_ctx->sigpos;
|
||||||
|
size_t signature_len = ctx->script_ctx->fileend - ctx->script_ctx->sigpos;
|
||||||
|
size_t base64_len;
|
||||||
|
char *ptr;
|
||||||
|
BIO *bio_mem, *bio_b64 = NULL;
|
||||||
|
char *base64_data = NULL;
|
||||||
|
char *clean_base64 = NULL;
|
||||||
|
int clean_base64_len = 0;
|
||||||
|
const char *open_tag = ctx->script_ctx->comment_text->open;
|
||||||
|
const char *close_tag = ctx->script_ctx->comment_text->close;
|
||||||
|
size_t open_tag_len = strlen(open_tag);
|
||||||
|
size_t close_tag_len = strlen(close_tag);
|
||||||
|
size_t signature_header_len = strlen(signature_header);
|
||||||
|
size_t signature_footer_len = strlen(signature_footer);
|
||||||
|
PKCS7 *retval = NULL;
|
||||||
|
|
||||||
|
if (!script_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
/* extract Base64 signature */
|
||||||
|
if (ctx->script_ctx->utf == 8) {
|
||||||
|
base64_len = signature_len;
|
||||||
|
base64_data = OPENSSL_malloc(base64_len);
|
||||||
|
memcpy(base64_data, signature_data, base64_len);
|
||||||
|
} else {
|
||||||
|
base64_len = utf16_to_utf8((const void *)signature_data,
|
||||||
|
signature_len, &base64_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for cleaned Base64 */
|
||||||
|
clean_base64 = OPENSSL_malloc(base64_len);
|
||||||
|
if (!clean_base64) {
|
||||||
|
fprintf(stderr, "Malloc failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy clean Base64 data */
|
||||||
|
for (ptr = base64_data;;) {
|
||||||
|
/* find the opening tag */
|
||||||
|
for(;;) {
|
||||||
|
if (ptr + open_tag_len >= base64_data + base64_len) {
|
||||||
|
fprintf(stderr, "Signature line too long\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!memcmp(ptr, open_tag, (size_t)open_tag_len)) {
|
||||||
|
ptr += open_tag_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
/* process signature_header and signature_footer */
|
||||||
|
if (ptr + signature_header_len < base64_data + base64_len &&
|
||||||
|
!memcmp(ptr, signature_header, signature_header_len))
|
||||||
|
ptr += signature_header_len;
|
||||||
|
if (ptr + signature_footer_len <= base64_data + base64_len &&
|
||||||
|
!memcmp(ptr, signature_footer, signature_footer_len))
|
||||||
|
break; /* success */
|
||||||
|
|
||||||
|
/* copy until the closing tag */
|
||||||
|
for(;;) {
|
||||||
|
if (ptr + close_tag_len >= base64_data + base64_len) {
|
||||||
|
fprintf(stderr, "Signature line too long\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (close_tag_len) {
|
||||||
|
if (!memcmp(ptr, close_tag, (size_t)close_tag_len)) {
|
||||||
|
ptr += close_tag_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*ptr == '\r') {
|
||||||
|
ptr++;
|
||||||
|
} else if (*ptr == '\n') {
|
||||||
|
ptr++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
clean_base64[clean_base64_len++] = *ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare for Base64 decoding */
|
||||||
|
bio_mem = BIO_new_mem_buf(clean_base64, clean_base64_len);
|
||||||
|
bio_b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_push(bio_b64, bio_mem);
|
||||||
|
BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
|
||||||
|
/* decode DER */
|
||||||
|
retval = d2i_PKCS7_bio(bio_b64, NULL);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
OPENSSL_free(base64_data);
|
||||||
|
OPENSSL_free(clean_base64);
|
||||||
|
BIO_free_all(bio_b64);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return script_pkcs7_extract(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove existing signature.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int script_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)hash;
|
||||||
|
if (!script_check_file(ctx)) {
|
||||||
|
return 1; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
if (!script_write_bio(outdata, ctx->options->indata, ctx->script_ctx->sigpos)) {
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
return 0; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize outdata file and calculate a hash (message digest) of data.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int script_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
if (ctx->script_ctx->sigpos > 0) {
|
||||||
|
/* Strip current signature */
|
||||||
|
ctx->script_ctx->fileend = ctx->script_ctx->sigpos;
|
||||||
|
}
|
||||||
|
if (!script_write_bio(outdata, ctx->options->indata, ctx->script_ctx->fileend))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!script_digest_convert(hash, ctx, ctx->script_ctx->fileend))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new PKCS#7 signature.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
PKCS7 *p7 = pkcs7_create(ctx);
|
||||||
|
|
||||||
|
if (!p7) {
|
||||||
|
fprintf(stderr, "Creating a new signature failed\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!add_indirect_data_object(p7)) {
|
||||||
|
fprintf(stderr, "Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
if (!content) {
|
||||||
|
fprintf(stderr, "Failed to get spcIndirectDataContent\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
|
fprintf(stderr, "Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append signature to the outfile.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int script_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
BIO *bio, *b64;
|
||||||
|
BUF_MEM *buffer;
|
||||||
|
size_t i;
|
||||||
|
static const char crlf[] = {0x0d, 0x0a};
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
/* convert to BASE64 */
|
||||||
|
b64 = BIO_new(BIO_f_base64()); /* BIO for base64 encoding */
|
||||||
|
if (!b64)
|
||||||
|
return 1; /* FAILED */
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
bio = BIO_new(BIO_s_mem()); /* BIO to hold the base64 data */
|
||||||
|
if (!bio) {
|
||||||
|
BIO_free(b64);
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
bio = BIO_push(b64, bio); /* chain base64 BIO onto memory BIO */
|
||||||
|
if (!i2d_PKCS7_bio(bio, p7)) {
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
(void)BIO_flush(bio);
|
||||||
|
BIO_get_mem_ptr(bio, &buffer);
|
||||||
|
(void)BIO_set_close(bio, BIO_NOCLOSE);
|
||||||
|
|
||||||
|
/* split to individual lines and write to outdata */
|
||||||
|
if (!write_commented(ctx, outdata, signature_header, strlen(signature_header)))
|
||||||
|
goto cleanup;
|
||||||
|
for (i = 0; i < buffer->length; i += 64) {
|
||||||
|
if (!write_commented(ctx, outdata, buffer->data + i,
|
||||||
|
buffer->length - i < 64 ? buffer->length - i : 64)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!write_commented(ctx, outdata, signature_footer, strlen(signature_footer)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* signtool expects CRLF terminator at the end of the text file */
|
||||||
|
if (!write_in_encoding(ctx, outdata, crlf, sizeof crlf))
|
||||||
|
goto cleanup;
|
||||||
|
ret = 0; /* OK */
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
BUF_MEM_free(buffer);
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free up an entire outdata BIO chain.
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void script_bio_free(BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
BIO_free_all(hash);
|
||||||
|
BIO_free_all(outdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate a FILE_FORMAT_CTX structure and script format specific structures.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void script_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
unmap_file(ctx->options->indata, ctx->script_ctx->fileend);
|
||||||
|
OPENSSL_free(ctx->script_ctx);
|
||||||
|
OPENSSL_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int script_is_detaching_supported(void)
|
||||||
|
{
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
static SCRIPT_CTX *script_ctx_get(char *indata, uint32_t filesize, const SCRIPT_COMMENT *comment, int utf)
|
||||||
|
{
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
|
|
||||||
|
const char *input_pos, *signature_pos, *ptr;
|
||||||
|
uint32_t line[LINE_MAX_LEN], commented_header[40], cr, lf;
|
||||||
|
size_t sig_pos = 0, line_pos = 0, commented_header_len = 0;
|
||||||
|
size_t commented_header_size = sizeof commented_header / sizeof(uint32_t);
|
||||||
|
|
||||||
|
utf8DecodeRune("\r", 1, &cr);
|
||||||
|
utf8DecodeRune("\n", 1, &lf);
|
||||||
|
|
||||||
|
/* compute runes for the commented signature header */
|
||||||
|
for (ptr = comment->open;
|
||||||
|
*ptr && commented_header_len < commented_header_size;
|
||||||
|
commented_header_len++)
|
||||||
|
ptr = utf8DecodeRune(ptr, 1, commented_header + commented_header_len);
|
||||||
|
for (ptr = signature_header;
|
||||||
|
*ptr && commented_header_len < commented_header_size;
|
||||||
|
commented_header_len++)
|
||||||
|
ptr = utf8DecodeRune(ptr, 1, commented_header + commented_header_len);
|
||||||
|
for (ptr = comment->close;
|
||||||
|
*ptr && commented_header_len < commented_header_size;
|
||||||
|
commented_header_len++)
|
||||||
|
ptr = utf8DecodeRune(ptr, 1, commented_header + commented_header_len);
|
||||||
|
|
||||||
|
/* find the signature header */
|
||||||
|
for (signature_pos = input_pos = indata; input_pos < indata + filesize; ) {
|
||||||
|
const char *input_prev = input_pos;
|
||||||
|
|
||||||
|
input_pos = utf == 8 ?
|
||||||
|
utf8DecodeRune(input_pos,
|
||||||
|
(size_t)(indata + filesize - input_pos),
|
||||||
|
line + line_pos) :
|
||||||
|
(const char *)utf16DecodeRune((const void *)input_pos,
|
||||||
|
(size_t)(indata + filesize - input_pos)/2,
|
||||||
|
line + line_pos);
|
||||||
|
|
||||||
|
if (!memcmp(line + line_pos, &lf, sizeof lf)) {
|
||||||
|
if (line_pos >= commented_header_len &&
|
||||||
|
!memcmp(line, commented_header, commented_header_len * sizeof(uint32_t))) {
|
||||||
|
sig_pos = (size_t)(signature_pos - indata);
|
||||||
|
if (!memcmp(line + line_pos - 1, &cr, sizeof cr))
|
||||||
|
sig_pos -= (size_t)utf / 8;
|
||||||
|
break; /* SUCCEEDED */
|
||||||
|
}
|
||||||
|
line_pos = 0;
|
||||||
|
signature_pos = input_prev; /* previous line */
|
||||||
|
} else if (line_pos < LINE_MAX_LEN - 1) {
|
||||||
|
line_pos++; /* we can ignore lines longer than our buffer */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Signature position: %zu\n", sig_pos);
|
||||||
|
|
||||||
|
script_ctx = OPENSSL_malloc(sizeof(SCRIPT_CTX));
|
||||||
|
script_ctx->comment_text = comment;
|
||||||
|
script_ctx->utf = utf;
|
||||||
|
script_ctx->fileend = filesize;
|
||||||
|
script_ctx->sigpos = (uint32_t)sig_pos;
|
||||||
|
return script_ctx; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write a commented line to the bio:
|
||||||
|
* - prepend with CRLF ("\r\n")
|
||||||
|
* - add opening/closing comment tags
|
||||||
|
* - adjust encoding if needed
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int write_commented(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *data, size_t length)
|
||||||
|
{
|
||||||
|
const char *open_tag = ctx->script_ctx->comment_text->open;
|
||||||
|
const char *close_tag = ctx->script_ctx->comment_text->close;
|
||||||
|
size_t open_tag_len = strlen(open_tag);
|
||||||
|
size_t close_tag_len = strlen(close_tag);
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
/* the buffer needs to be long enough for:
|
||||||
|
* - CRLF ("\r\n")
|
||||||
|
* - opening tag
|
||||||
|
* - up to 64 bytes of data
|
||||||
|
* - closing tag
|
||||||
|
* - trailing NUL ("\0") */
|
||||||
|
line = OPENSSL_malloc(2 + open_tag_len + length + close_tag_len + 1);
|
||||||
|
strcpy(line, "\r\n");
|
||||||
|
strcat(line, open_tag);
|
||||||
|
memcpy(line + 2 + open_tag_len, data, length);
|
||||||
|
line[2 + open_tag_len + length] = '\0';
|
||||||
|
strcat(line, close_tag);
|
||||||
|
|
||||||
|
/* adjust encoding */
|
||||||
|
if (!write_in_encoding(ctx, outdata, line, strlen(line))) {
|
||||||
|
OPENSSL_free(line);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(line);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adjust encoding if needed
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int write_in_encoding(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *line, size_t length)
|
||||||
|
{
|
||||||
|
size_t written;
|
||||||
|
if (ctx->script_ctx->utf == 8) {
|
||||||
|
if (!BIO_write_ex(outdata, line, length, &written)
|
||||||
|
|| written != length) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint16_t *utf16_data = NULL;
|
||||||
|
size_t utf16_len = utf8_to_utf16(line, length, &utf16_data);
|
||||||
|
|
||||||
|
if (!BIO_write_ex(outdata, utf16_data, utf16_len, &written)
|
||||||
|
|| written != utf16_len) {
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert len bytes of UTF-8 to UTF-16
|
||||||
|
* return the number of output bytes
|
||||||
|
*/
|
||||||
|
static size_t utf8_to_utf16(const char *data, size_t len, uint16_t **out_utf16)
|
||||||
|
{
|
||||||
|
size_t utf16_len = utf8UTF16Count(data, len);
|
||||||
|
*out_utf16 = OPENSSL_malloc(utf16_len * sizeof(uint16_t));
|
||||||
|
if (!*out_utf16)
|
||||||
|
return 0; /* memory allocation failed */
|
||||||
|
|
||||||
|
const char *s = data;
|
||||||
|
uint16_t *d = *out_utf16;
|
||||||
|
uint32_t rune;
|
||||||
|
size_t remaining_len = len;
|
||||||
|
|
||||||
|
while (remaining_len > 0) {
|
||||||
|
s = utf8DecodeRune(s, remaining_len, &rune);
|
||||||
|
if (!s || s < data)
|
||||||
|
break; /* invalid UTF-8 sequence */
|
||||||
|
size_t consumed = (size_t)(s - data);
|
||||||
|
|
||||||
|
remaining_len -= consumed;
|
||||||
|
data = s;
|
||||||
|
d += utf16EncodeRune(rune, d);
|
||||||
|
}
|
||||||
|
return (size_t)(2 * (d - *out_utf16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert len bytes of UTF-16 to UTF-8
|
||||||
|
* return the number of output bytes
|
||||||
|
*/
|
||||||
|
static size_t utf16_to_utf8(const uint16_t *data, size_t len, char **out_utf8)
|
||||||
|
{
|
||||||
|
size_t utf8_len = utf16UTF8Count(data, len/2);
|
||||||
|
*out_utf8 = OPENSSL_malloc(utf8_len);
|
||||||
|
if (!*out_utf8)
|
||||||
|
return 0; /* memory allocation failed */
|
||||||
|
|
||||||
|
const uint16_t *s = data;
|
||||||
|
char *d = *out_utf8;
|
||||||
|
uint32_t rune;
|
||||||
|
size_t remaining_len = len/2;
|
||||||
|
|
||||||
|
while (remaining_len > 0) {
|
||||||
|
s = utf16DecodeRune(s, remaining_len, &rune);
|
||||||
|
if (!s || s < data)
|
||||||
|
break; /* invalid UTF-16 sequence */
|
||||||
|
size_t consumed = (size_t)(s - data);
|
||||||
|
|
||||||
|
remaining_len -= consumed;
|
||||||
|
data = s;
|
||||||
|
d += utf8EncodeRune(rune, d);
|
||||||
|
}
|
||||||
|
return (size_t)(d - *out_utf8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a message digest value of a signed or unsigned script file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] calculated message digest BIO
|
||||||
|
*/
|
||||||
|
static BIO *script_digest_calc_bio(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
size_t fileend;
|
||||||
|
BIO *hash = BIO_new(BIO_f_md());
|
||||||
|
|
||||||
|
if (ctx->script_ctx->sigpos)
|
||||||
|
fileend = ctx->script_ctx->sigpos;
|
||||||
|
else
|
||||||
|
fileend = ctx->script_ctx->fileend;
|
||||||
|
|
||||||
|
if (!BIO_set_md(hash, md)) {
|
||||||
|
fprintf(stderr, "Unable to set the message digest of BIO\n");
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_push(hash, BIO_new(BIO_s_null()));
|
||||||
|
if (!script_digest_convert(hash, ctx, fileend)) {
|
||||||
|
fprintf(stderr, "Unable calc a message digest value\n");
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a message digest value
|
||||||
|
* [in, out] hash: message digest BIO
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] len: mapped file length
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_digest_convert(BIO *hash, FILE_FORMAT_CTX *ctx, size_t len)
|
||||||
|
{
|
||||||
|
if (ctx->script_ctx->utf == 8) { /* need to convert to UTF-16 */
|
||||||
|
uint16_t *utf16_data = NULL;
|
||||||
|
size_t utf16_len = utf8_to_utf16(ctx->options->indata,
|
||||||
|
len, &utf16_data);
|
||||||
|
|
||||||
|
if (!script_write_bio(hash, (char *)utf16_data, utf16_len)) {
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
} else { /* already UTF-16 -> no need to convert */
|
||||||
|
if (!script_write_bio(hash, ctx->options->indata, len)) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write len bytes from data to BIO
|
||||||
|
* [in, out] bio: message digest or outdata BIO
|
||||||
|
* [in] indata: mapped file
|
||||||
|
* [in] len: indata length
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_write_bio(BIO *bio, char *indata, size_t len)
|
||||||
|
{
|
||||||
|
size_t i = 0, written;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
if (!BIO_write_ex(bio, indata + i, len, &written))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
len -= written;
|
||||||
|
i += written;
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the signature exists.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "Init error\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->script_ctx->sigpos == 0
|
||||||
|
|| ctx->script_ctx->sigpos > ctx->script_ctx->fileend) {
|
||||||
|
fprintf(stderr, "No signature found\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
2
tests/.gitignore
vendored
Normal file
2
tests/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
__pycache__
|
||||||
|
.pylintrc
|
@ -1,22 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDoTCCAomgAwIBAgIUOK8lwJ8A1Oqw8jDAb3TF06ve+PcwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTcwMTAxMDAwMDAwWhcNMjYxMTEwMDAwMDAwWjBYMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEQMA4GA1UEAwwHUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
|
||||||
AQoCggEBAKzObJwYq4t9Y/OOQLqUNLU8RDXq284L8zQgRLkvApF87FNN7kozIgC9
|
|
||||||
/HAgJSho/Lup5lzkCWa3fjkYm1EBrL+JihesSaCxxe7LOg6tRaY+WxikwMUnlkNE
|
|
||||||
s3R+DogeGVsla4q0FEcICiz3FHTfSAUVmrN3Nj1ll7npJXrqmXxfCuO3slgjUkHq
|
|
||||||
tdZ5t1rSWwbiUhGIQKLzo3/uw2XoOI28qpoOw+0/y8AyjWs8My3u8GrYFr+qh5fx
|
|
||||||
Y0Zp0EhhAJo23Xd43XmeVKjuKIOaHu3JiM8sp9K1WFsTvFNAO27TBRn/X0mJCeDX
|
|
||||||
T117dQxhWOCcQ/uRGuXICT4ign8MLtUCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB
|
|
||||||
/zAdBgNVHQ4EFgQU6ewx3DIpbR8OptEmDFlYNELRqP4wHwYDVR0jBBgwFoAU6ewx
|
|
||||||
3DIpbR8OptEmDFlYNELRqP4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUA
|
|
||||||
A4IBAQAhRMun0IzPmHVFM+SOfSCPVAgogWpqR5XlBAFlS+Aen6v3ukQAQjEhfBbE
|
|
||||||
dZG6ye9i0ebf9qXYTvSq5wfaqP7FGb2/Z96uPXNMXPi796KjLW2CG578DitORPb7
|
|
||||||
x1eV3UGrQX2bMQ0JbGkBU+DIdIRBqDfad/kjLtm5eHyCbaodSWdaZO4LSUIy3MBx
|
|
||||||
2UeBj2qD4RTA0Dt7hG7RA5QdTxHlZyLIk8HX3krZ+il5RmSbOnQs/XqK5DJp4J5p
|
|
||||||
122sIO4Y9ki+Wewzx8f3/7mcVbcMo67GwRHo8bk3GjWE74pczyrzfP68vDQ4tn85
|
|
||||||
NcLPeLClfSziJD09z+Iyp94EQeKX
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,13 +0,0 @@
|
|||||||
-----BEGIN X509 CRL-----
|
|
||||||
MIIB9zCB4AIBATANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJQTDEVMBMGA1UE
|
|
||||||
CgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
|
|
||||||
eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBFw0xOTAxMDEwMDAwMDBaFw00MzAx
|
|
||||||
MDEwMDAwMDBaMCcwJQIUOpY5wp7DtqsdxII7sxculedk0PYXDTIyMDcyNjEzMDk1
|
|
||||||
NlqgIzAhMB8GA1UdIwQYMBaAFJ4FrAtb4UB/ag702URPiid97ziLMA0GCSqGSIb3
|
|
||||||
DQEBCwUAA4IBAQA4Kw0vEJrtjjMam16iN/stOMxJDgkp1IQzA3narxr9fEjX5Ynk
|
|
||||||
JztuEExtowPIDOLGWCySXNEMmxCzXNAMvlUq+UQvnWrwgHQ9R7TBYIcAY+VRmzKz
|
|
||||||
T4PXvDSL2WMuJ1dLWoIcL2D0wEdti7YMvAnCrOC8HAPGgke5QcOgSfMSAYSAtpiw
|
|
||||||
PZAFgcuo53AodlCw9J+CPcHPYw+C2QExOy8s8q6d8Xgjg+Ge7v3RxLWy74sNPl0u
|
|
||||||
uZ79vcLNEeqEXxKaw5abqDqIDcUKIT3b62KsSxkak9IGNMLcTASw1V+YaKVLSYNW
|
|
||||||
NTuc5WJblfZi/q7WUMKkmRERzvdg2rf0CSH1
|
|
||||||
-----END X509 CRL-----
|
|
@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCivbbTCnbOqPoV
|
|
||||||
7VVP/KJzgslx8yfX9laGwTsvzqStQtG8j40ljR85WD/bgy3I5duebudg7JhOVH2f
|
|
||||||
aSqbh8SCzP4YNDFcseDIuHdoXi54POgW3S/wbe8l8P7g3btcBgnlXh/izhUlEMib
|
|
||||||
Q/8G8UZj0n/MgKMLzcXc4t2eQ4Pzw7xAPqoXBZ20Fg2rFBfUsDDLc5F7lpO5t1WQ
|
|
||||||
dXTYmF0oAL/HLmd+HKe5Xgp9jJ6XacesjWLnhRdZ06uUP9cgo+Jem4QZxeFhOtMe
|
|
||||||
KAf7JH3Juz2Gi0a+4dMSNzES4m8RAlf6pXh4kAh7EhMNb/Ir6ZpY8uKM7dtn38mh
|
|
||||||
1f59EKc9AgMBAAECggEAK5zB0P695hYcpyGqOjxO4LvM9m+eXt7SQ1ynWuF6+j+s
|
|
||||||
62ZhAg42rux6eH5IF82ZtHSuJyhgjKVR4RWS6IlS3WbINX5PODMnNUNSJLMQqwJP
|
|
||||||
hEkUXs9nRni2JVbmrfukTUaTLvnhasR7rjhjsN2Z6ohv3UMf7rrfapmVoKMhSoLd
|
|
||||||
jqvZ2ZoaT5mfTiK/5PDyWqrt/vmvE4VlipAsvudwozG5vQDEsCNDNUTg5OTGnPUU
|
|
||||||
i0xeQTioqzCcweIlEaWhj/eMHx/eAeZ6V0Evid/YwTDlbTqVDWZGLJ/phOnKJs3V
|
|
||||||
j+eOv7E2d1ga7149SPDIv5Y0YZ91v3M06ICk5o66gQKBgQDSM+YyR5YOJTSAuAcI
|
|
||||||
uKTc33wwCbPiJF/F1zLJDdPp2IamZQbuNIX/8fOG3Gho+OnfNAykMcr3rFrug2vi
|
|
||||||
9GhWDQqguYGh16xos+2zNan6P/s0/rQ4OfPIsTEGC8X3fJeMzZUNMvnyN/FXzzus
|
|
||||||
020o29gu59esEfGHEsvAupC3IQKBgQDGMqGLgrU4oW/5mmm4BZlwwkZJNMmFH49u
|
|
||||||
Qe4Ylj87SQduExJMmTfrmANqQXu7RXG0IxLcvhwMLVCCYAkvuBv1awsbg2yfP1Pn
|
|
||||||
Wb/K+5CaHaxnpwSpRiGaN6fnAPDl8PnALMVXtQGru2MMcISxOIFQ9slHth0lmaMo
|
|
||||||
odIPIL1YnQKBgAOSskUEhn5zD3NorWXujY7blabTY2VirOYWBFz6iTGeZpuJeBaw
|
|
||||||
ed6h5DvUn0m5gXAz2EsqNYMEQP9w6HKRKPzdd+LHhHaVze5xsIatUNhaIhECi1mx
|
|
||||||
Un2E1Yp+xLyyN3lDPVdeGHWPkeCmOyNy7JYXNpOFiVr5axuarC/4e+FBAoGAeuRR
|
|
||||||
/mshaufOwnnYK15tcdlEM4gjnAOhr7/5ng0rT9tMXBg/NHeckNxE4dGQouHASu2k
|
|
||||||
eHL4eSRv0ycxCwGhdF7XGEw5QdTGdaDUp0ussaLMj8ijv0HY/AKefUG8HRd6BIq+
|
|
||||||
Ik/9pTofhEsQO8LJjCY5T9m/4NyOqlcMJI0sWpECgYBvPLnutbBXYONVAE3jL05K
|
|
||||||
hWwenKpv5Aaa11ahqzhil2Tj+VOMtmvhsSc5loSG83qp5LtN4LxyR0Vn9AGN7Z+d
|
|
||||||
Ut6LHeZ/DMW3/RPT+1MIKm6WLNxgk5YvuCxprdpfE5tTmV9/t+t3Uao7TRsLPl2o
|
|
||||||
qAKz8Fvq0el5RW3EtAgd4A==
|
|
||||||
-----END PRIVATE KEY-----
|
|
@ -1,28 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEzTCCA7WgAwIBAgIUfRjXKciCGA4XbhbhxbAwfpcLGmowDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xODAxMDEwMDAwMDBaFw0yODAxMDEwMDAwMDBaMFUxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxHDAaBgNVBAsME1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkxETAPBgNVBAMMCFRlc3QgVFNBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
|
||||||
AQ8AMIIBCgKCAQEAor220wp2zqj6Fe1VT/yic4LJcfMn1/ZWhsE7L86krULRvI+N
|
|
||||||
JY0fOVg/24MtyOXbnm7nYOyYTlR9n2kqm4fEgsz+GDQxXLHgyLh3aF4ueDzoFt0v
|
|
||||||
8G3vJfD+4N27XAYJ5V4f4s4VJRDIm0P/BvFGY9J/zICjC83F3OLdnkOD88O8QD6q
|
|
||||||
FwWdtBYNqxQX1LAwy3ORe5aTubdVkHV02JhdKAC/xy5nfhynuV4KfYyel2nHrI1i
|
|
||||||
54UXWdOrlD/XIKPiXpuEGcXhYTrTHigH+yR9ybs9hotGvuHTEjcxEuJvEQJX+qV4
|
|
||||||
eJAIexITDW/yK+maWPLijO3bZ9/JodX+fRCnPQIDAQABo4IBiDCCAYQwDAYDVR0T
|
|
||||||
AQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAdBgNVHQ4EFgQUKWCqogni
|
|
||||||
6SseJ/P6LXo0M2cK++QwHwYDVR0jBBgwFoAU/5nNuG4Tm4v2y9uKf428/4fVQesw
|
|
||||||
gYQGCCsGAQUFBwEBBHgwdjA5BggrBgEFBQcwAoYtaHR0cDovL1RTQUNBLnRpbWVz
|
|
||||||
dGFtcGF1dGhvcml0eS5jb20vVFNBQ0EuY3J0MDkGCCsGAQUFBzABhi1odHRwOi8v
|
|
||||||
b2NzcC5UU0FDQS50aW1lc3RhbXBhdXRob3JpdHkuY29tOjkwODAwPgYDVR0fBDcw
|
|
||||||
NTAzoDGgL4YtaHR0cDovL1RTQUNBLnRpbWVzdGFtcGF1dGhvcml0eS5jb20vVFNB
|
|
||||||
Q0EuY3JsMFUGA1UdHgROMEygGDAKggh0ZXN0LmNvbTAKggh0ZXN0Lm9yZ6EwMAqH
|
|
||||||
CAAAAAAAAAAAMCKHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA0G
|
|
||||||
CSqGSIb3DQEBCwUAA4IBAQB4YXa5nVWUzWSsUDMfYFTEETOe8boUErwfrDNBuj6z
|
|
||||||
B5en20FhI49i6PCYEfNq3vrAtPOEFJj+KPomN3C46VLxbUEvqWLdq6EyzWvVVmXK
|
|
||||||
VLeC0qV0m6CFM8GplaWzZdfFTQaaLUhgY08ZU2gp4QsoS2YjAosxlZrNSm6pBbv3
|
|
||||||
q+Og1KeSK8gKS0V89k+6e3LOEF6KaNWKSkoz5xDniQY//mTjiDcNmYUh0KhHfhdU
|
|
||||||
eO92M82uJSaDqnRs5HsWPs6z6qdfpuvj++OtQ1VCM2p5SEH2sEomdeN3YYChuG4h
|
|
||||||
yzn0mYAdbTyGJHlFm17AH+SQRbVqCKYdHDaqsMb+fWzi
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,22 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDkDCCAnigAwIBAgIUJ0nfE+EVsIThltlY2LHVWMJVIq4wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xNzAxMDEwMDAwMDBaFw0yNjExMTAwMDAwMDBaMGAxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxJDAiBgNVBAsMG1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkgUm9vdCBDQTEUMBIGA1UEAwwLVFNBIFJvb3QgQ0EwggEiMA0GCSqG
|
|
||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGOTX1f9dmtUiyzlsUInRIGfRMya338SVx
|
|
||||||
vYGeOwdpTSSGlYUVwR9AuFewQF5+klelstCJe+SoUG0AdzS30mRWlQrhip4UdvdW
|
|
||||||
T2gkNKbSn6DQzlWoQej9izqRLxAsbuszgkvnLOBEmPaLimDsCgu0bAN95Hp0Hls9
|
|
||||||
O/fVmzh8VuV4iscxc7q13ZB7CylWgwd55CFEGd/jpJ6kMwSHbOLoBWp4GQ3KxR+c
|
|
||||||
ASAo0FapU2WSZB2EYWszRiyq91X+AvIYN4ypTv7RccgfUvnZ2qFykJAkf/wgkynu
|
|
||||||
Qg7rCUNfUEpDc7jlqtDWR7iLrtHBkA17C3IU8ymmKQYWfw3ZyBwvAgMBAAGjQjBA
|
|
||||||
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP+ZzbhuE5uL9svbin+NvP+H1UHr
|
|
||||||
MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAbj3aFwIUxvzwgywO
|
|
||||||
gj01JM8GNbw1E4MGdkaNI8rgeY8ay15ZXhR9NpRWWb6Y7IXPq5XhuEktVte5Z4Kf
|
|
||||||
XLBrr7Xe9VVqJL9zd1tMzOEM/zG77rZf/iXBTZLkCtQc/GOEY4TTWKNEl5hiWVE0
|
|
||||||
po97GX5XHoeyHlWQ75sd9z6MxFxmvdp9/uyYD700e9sd5gcD8LGvHw2DNy8vntYV
|
|
||||||
ia9h95N9i1umffxU460o8W5GoIcsD13B3YftvnWhGSXqovBRFgcPAQZ4eW9Qh/zA
|
|
||||||
4zQBQrRvmREPihXVdgtWVpbRchP99oSZBrYr7Hh/P69rycklquqxJl1ol1wbT6dK
|
|
||||||
S5Gmng==
|
|
||||||
-----END CERTIFICATE-----
|
|
Binary file not shown.
Binary file not shown.
@ -1,46 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIID7jCCAtagAwIBAgIUdLInHjkevRVCr7I78r5++6eSrZ0wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0yNDEyMzEwMDAwMDBaMIGdMQswCQYDVQQG
|
|
||||||
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
|
||||||
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEUMBIGA1UEAwwL
|
|
||||||
Q2VydGlmaWNhdGUxJzAlBgkqhkiG9w0BCQEWGG9zc2xzaWduY29kZUBleGFtcGxl
|
|
||||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJLJ3Vty2lgJw+5
|
|
||||||
ouAV4ZqkIwvfWPcE7zD1CfQIL2802jVuCSTkN9cfFVYMKFEPJxQWJAKoCzr/Ux8z
|
|
||||||
Yt9BXO5o39+z7umLKmc6pfrZJ6kG4msrMjZv36LsCQyfjUc1O9H1aiOQEvRQY2pF
|
|
||||||
2v5dfqRMrAqH1ESQHCggUBjElWj9oMFax8jyO7JxTzuttOb6mhDmqz4q2u4LwZGH
|
|
||||||
lBofgOAB54Mlv41x7dDh85i/jayXuYYmsjRwCuBAn14+D2zImyPDx5UaUJJMzujo
|
|
||||||
QriOZ4KU2dHRgy0+vd7ZbrL1kRY1axyNQ+jBk7UHnlZZ2CCkhBoZIM6ez3ljPwgr
|
|
||||||
cpg0RtcCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUBxPEs09WXDxGqb+D
|
|
||||||
WTFgcUQd0AEwHwYDVR0jBBgwFoAUngWsC1vhQH9qDvTZRE+KJ33vOIswEwYDVR0l
|
|
||||||
BAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAKK2e1s1puUFbNjglopi
|
|
||||||
mKZ4Pks2zb6LVUGG6Q4XQ1dWe25ovt68jWv56HFyCMI1N+L8q0+Ku2eOfLObS7Ej
|
|
||||||
FFRUWEIXDgipryDTGzoWRM380fuYpL/j7Rt1/xmIHWTFibf/6gK/naRXsFH3dEbb
|
|
||||||
7DDWQ5pAd2d60dB+ThUEIZQTQd/926Kuk5oESvP08fXMYTuiYARypG1gmiuvxQ9N
|
|
||||||
mDJP6CHxyJR/LB4tb0RAqnLkVsXVBDnRYWdEvkuhoqTtbhVzVbL3mPeEmVYypxxd
|
|
||||||
NdrHpU5zmxFSin2T3F0TneNcT+MDV+dQcWyTGNYs/fnmo85LsiakJixGv1qx8PTs
|
|
||||||
8iE=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
Binary file not shown.
@ -1,23 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDzjCCAragAwIBAgIUGjZdQYlcAtlqZOsQ7eWRimQ9PIcwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwbzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEMMAoGA1UE
|
|
||||||
CwwDQ1NQMRIwEAYDVQQDDAljcm9zc2NlcnQxJzAlBgkqhkiG9w0BCQEWGG9zc2xz
|
|
||||||
aWduY29kZUBleGFtcGxlLmNvbTAeFw0xODAxMDEwMDAwMDBaFw0yMDA2MTkwMDAw
|
|
||||||
MDBaMG8xCzAJBgNVBAYTAlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNV
|
|
||||||
BAsMA0NTUDESMBAGA1UEAwwJY3Jvc3NjZXJ0MScwJQYJKoZIhvcNAQkBFhhvc3Ns
|
|
||||||
c2lnbmNvZGVAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
|
||||||
AoIBAQDJU6WNMOEoErLYb5Qc7jsvVgruPM7DJTZ4vUpJNYAyprSDHciaKSa4SiYS
|
|
||||||
84Mxc6tzBoJvKOAwpxzzONOqPVWUd5J244urgvfHgSGWsbA8bakiIYlETopnecFk
|
|
||||||
B3ZELR33CPqIbpYYMYujhPGFa1xxZxFykJ1iBhZ8Gh3W4wHi/2kW6hTQkihMtUPP
|
|
||||||
Xxc2XWACj/tz22OSdgNZcIfhXiy2HOuPch+0UlDR4UmlJIR5aet1y832hHoeeevo
|
|
||||||
qfhfGOm9rRf9nyxKDwTyaN7JVOb7A1k6KJEJoe1zfIwT56mgoA433iUWFMLB6hKU
|
|
||||||
be3zV1vGjk77Kk7atcvEMTRq+rwHAgMBAAGjYjBgMAkGA1UdEwQCMAAwHQYDVR0O
|
|
||||||
BBYEFEXgglEcDh+8oCCvjlxrN/Y7C4YwMB8GA1UdIwQYMBaAFEXgglEcDh+8oCCv
|
|
||||||
jlxrN/Y7C4YwMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IB
|
|
||||||
AQBo8UqUEjxGQCVU/IgphwKA8Rb/uAyBYm+AjqFDs82lA6ze0n08Bj+eciVkxscA
|
|
||||||
0deivOC1sDD88QkLzSQ9CPk4e7+m7nx5SFUnUWY+o3ln+cTbGSM0jW9hme0LtHXX
|
|
||||||
QxDSKDBhQonRQk7lQ+TwFR7ol+y5SdZy7YQ+v/25qO6MMQgSPykJIa4vF7lwrYhu
|
|
||||||
qL+1MJx/ryTbCUExcKNNkWHZJRc9ZvtdWEHYpBSZl5xmJdKMLnHAu5uv8N2pezzp
|
|
||||||
PfujldZky7bnERaTM+bf/LvKXS8RfQGrCLu9QjgPVa6ysZV6gXTsEtwYh64vucjS
|
|
||||||
s7IhdLxfiT0xYkK4JWrRLc38
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,45 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIID6jCCAtKgAwIBAgIUdtBZJAw8/6JVNMiQpN3PEROI8rowDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMIGZMQswCQYDVQQG
|
|
||||||
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
|
||||||
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UEAwwH
|
|
||||||
RXhwaXJlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUuY29t
|
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsksndW3LaWAnD7mi4BXh
|
|
||||||
mqQjC99Y9wTvMPUJ9AgvbzTaNW4JJOQ31x8VVgwoUQ8nFBYkAqgLOv9THzNi30Fc
|
|
||||||
7mjf37Pu6YsqZzql+tknqQbiaysyNm/fouwJDJ+NRzU70fVqI5AS9FBjakXa/l1+
|
|
||||||
pEysCofURJAcKCBQGMSVaP2gwVrHyPI7snFPO6205vqaEOarPira7gvBkYeUGh+A
|
|
||||||
4AHngyW/jXHt0OHzmL+NrJe5hiayNHAK4ECfXj4PbMibI8PHlRpQkkzO6OhCuI5n
|
|
||||||
gpTZ0dGDLT693tlusvWRFjVrHI1D6MGTtQeeVlnYIKSEGhkgzp7PeWM/CCtymDRG
|
|
||||||
1wIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBQHE8SzT1ZcPEapv4NZMWBx
|
|
||||||
RB3QATAfBgNVHSMEGDAWgBSeBawLW+FAf2oO9NlET4onfe84izATBgNVHSUEDDAK
|
|
||||||
BggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAX1Ar7jRAXdcA0Wu37yRi58QN
|
|
||||||
hpa1VLXadqfB+i5Y4e3DzqnMbpkLWsFzreC1AG0RjLe52s4PRUE6boGlpUeAyfFC
|
|
||||||
Qu2Gl/REVWwMCYV8bq3vQZkYQjklAXCQLWFk5TrzuDmBcV8+fY518nWw+xmcYwW5
|
|
||||||
5oehLsvB4nxoBzlHgcdDwS5b2dmpCKCbZFLU9aA9DjAVvY/9B8emyj7Sh2sEK0Yf
|
|
||||||
xwHlATTVq5O0/9tvVZQmYsbpS0iCRGBM+spTEhDT4WGsaRO6wP+Ucgp6Ym3ahMvz
|
|
||||||
tHME3uUanKWVoDb69sguGZ6KlnZZZdIX1AJ3dlTXCrzEO9xsoAzqzsxVJGrraQ==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,22 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
Binary file not shown.
@ -1,27 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEogIBAAKCAQEAsksndW3LaWAnD7mi4BXhmqQjC99Y9wTvMPUJ9AgvbzTaNW4J
|
|
||||||
JOQ31x8VVgwoUQ8nFBYkAqgLOv9THzNi30Fc7mjf37Pu6YsqZzql+tknqQbiaysy
|
|
||||||
Nm/fouwJDJ+NRzU70fVqI5AS9FBjakXa/l1+pEysCofURJAcKCBQGMSVaP2gwVrH
|
|
||||||
yPI7snFPO6205vqaEOarPira7gvBkYeUGh+A4AHngyW/jXHt0OHzmL+NrJe5hiay
|
|
||||||
NHAK4ECfXj4PbMibI8PHlRpQkkzO6OhCuI5ngpTZ0dGDLT693tlusvWRFjVrHI1D
|
|
||||||
6MGTtQeeVlnYIKSEGhkgzp7PeWM/CCtymDRG1wIDAQABAoIBACR/jgxT9ZgUvupR
|
|
||||||
Li6BTDXD9AiyKBwpPm3fO7JhGpTBVQorBGQw891t14hN5NLzLyTFg4mnrOTe770r
|
|
||||||
X8okL0n+3hWFWBsnCf8n2mKHob7QUfluVlEehcFsYE3dO6agFybb/mZZUAgDjNZs
|
|
||||||
hnAb45juuSlOtP10Is90DfGEDLH5IeY1xjzc7Qv/CFxCffIAC8QmQYUTihJ2m5aE
|
|
||||||
7Hvs79oEcSvbRJDYbykzrJ0eeIaEvfOxkWJnnJHrhiONzb8qgj3DLiZdX1qeo1Ao
|
|
||||||
ldNxEG9n3Axd6M0nhajz0qbDV11S8YiKfP10XRQh5xv7lZi7MjvrRxFTFYpSrXwi
|
|
||||||
YYyFNoECgYEA6YnIYg1nIe3qaI3Me1RQQTGRl8M/dQc2d98Pz5mez9vN3TIW6nEs
|
|
||||||
QYw/9OKG1ercbD+YnuaV+1izuAcA3mNlSDReTtzInAotJjTH1V3WYqvBTVUZSb6T
|
|
||||||
5qSBfRDC3AULFvHeX5c5wqgfB3U9KLDfVBfaHnMerg6dAGsYZPhPMrkCgYEAw3Eg
|
|
||||||
5BRTzbqG0WXF25rycTeHCcylMZRjI+TVcIa8AGqNSCK4HgAWp89XPIV3WceVqe2R
|
|
||||||
Lyn1jtA2MgGGcMBDFlOWF+h9j2/j27Z+pyIbBF9LAraJuBOG6dezd50y5Ur6HK/f
|
|
||||||
e5lnjvElIYdz+RX+rmw8NFcIUbSAfE7rGinDvg8CgYBDx86VzsgJC/FFySn4/X6R
|
|
||||||
fV6BSpTHVYGUhvQiz7ZNI8F7GoeWIaSznY4OeBSkT5cL/+U+8TPEkHkQx0+UPArw
|
|
||||||
Suq4PtImn7l85kK9hY+scacX18QQKDTq8wH2F4BGtVwDm81rtwt3mK3wzzEh9zvK
|
|
||||||
P2X6AnV8FReyQGMDIyJxWQKBgD6nu9WitqMTkzj6GY4nhGXLWV1I4ASe/5F4QPzM
|
|
||||||
FOVFQ3nGt6PWf2zYyay7VOHRXCeX451tJC3ejiFF3+WxnVBBB7Muc2JSiofbX4sR
|
|
||||||
Ifwq2I9MGaaLjArXfc9w8+oSOVCNCWZEbbCjmjW/iOxnorgkNsDIzf/zj+VKH5DJ
|
|
||||||
ptj9AoGAUpB6nPES3Nnj8DsbpHCnShYMl/rFxzxg2pJJosXzuS/ttuBT2DlT5eiY
|
|
||||||
aZcL1DGSp2CD4QXbVuDHPkQMPzVfZzKAuCZlotEMR9byK46aYIkQueym45e0PGZP
|
|
||||||
djKZm+cxF+W55jBkBBhV6wSOLNRWCUYiIIq3RmwWjkopNvSlwY4=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
Binary file not shown.
@ -1,30 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
Proc-Type: 4,ENCRYPTED
|
|
||||||
DEK-Info: DES-EDE3-CBC,6DB255395263EDD5
|
|
||||||
|
|
||||||
A83CH4mv7u89RbT8Tpz4gxImKGBw69Zr3LstRXlliGYobby5YBx/YimkA9wFCZK/
|
|
||||||
B1eitWwy0F6axDZQYHKi+yvUJDPB9arXtClvYknMhwrHV1GHLSYeqb9oZJeqNyDZ
|
|
||||||
Qd3lxTbUtkMVJgJNrl2kOezm6/srnAw4uA7NyAvrs2vEzB48q4VlysrJq+f9mLXj
|
|
||||||
vCmrfUwY999lSifRmoxqeWlqNUQ2tgHHXYMNagpvxYXsfe1UvEH9aa6+UsO9S0py
|
|
||||||
7dyfSu95QpWyVNqkWi1VAtNbo2VpjJ6NJLAk+dy/rNqN3a4KnWeIzkYssWTsKB08
|
|
||||||
VyHrRLePPx5qdarsczZtf+M2PxhHHnl/09+Nrp5BUcMV31j3v3VSM0K+CHEucAk7
|
|
||||||
95rUtSUNywKUQeSgXrG1eLX7kXwRQ7PPCz3sPtvmJRIvQlGgLiTbKPsG52m3kAIw
|
|
||||||
zgXPcH2lYb3855occznl72jMUucxXq8gq0bC4xbEg/yJV8p1IuUEFhLGI9s9T4JV
|
|
||||||
cO9NKwmSjpHFo1ULhB7o6uMmV2rYDK+5GbQHxZgHj3ES+i53eFMWGubPEEOmqSh3
|
|
||||||
9K7gtW9y971tNfhp9ba8RnYXT6xW2nMTM4koO9b4ptdwRo5bMKFvWY8eecXfsDAG
|
|
||||||
OJ+aXkDr8jsn1Xauq1m4TM71wn2wUx95KaCpL55UNBEn7aH9qlNFfxdyzXMPYS36
|
|
||||||
zgWK44BV3PTSIGgW61NVwHwzi3bFfymortVxGpelzy2dggWVvI3uzKocLFQ8f4oe
|
|
||||||
Y0HWSmGVPF3uFHNCZtCB/Tpbz6YwP/YYStqAcryeS5Yo9Hdkh8pBVnYiKdTFEUW2
|
|
||||||
RbClgeB2MV+zttsqvmodfkviS4BjWgoIV5szxWOePnO8kQAHA/Ml3CyDPOX6rqI5
|
|
||||||
lDKiUojEMLgir/3YWWcmigEIgRsyF3CL1s+kTR3S8e9QRe8RiliRUKW5gXrLEa6j
|
|
||||||
eUjs4kgCrvmQvwyZYJjWl+r7ycmk+yB/EZs8P39KRR/pfeZDUCZIOx8vkJBt57hC
|
|
||||||
oTNJ5llFzRcmEraElXmDOAuvmj3Lx/4qzY545rtzll3mFHJEX4qITslIX1ksZz1p
|
|
||||||
DncuqgIECzmZIeHPbnw7Nkv6EkoPzTOlccqnCH/SumFr2fhctv9x13gGcO4kSsqO
|
|
||||||
63yZCFHjMz/mos3l51aIAizj5wQO3BOo+RyKoSQohvPzVtSgjhYMZsAPzXKxF0/H
|
|
||||||
9VH0DekEb1WwPSbGZw8kpx9ePlglGqOBinTL6QW8YmFPbjy9RDd1di+fxh4Qe024
|
|
||||||
8gERZpdSsMoZ+NP0nr/TSbDISFPqcLzzMpC+V8Fc/QkNvSkR1GLlNQrxLoyfK0VX
|
|
||||||
0evysXDxqIWK9+TH7hIS1lf3i2gMkLMppMso1v2Cqf0zRj1oM3MI743QE9XTXKRz
|
|
||||||
iAwaEDDPZWS/00T9fqNrHgtSPNpsbeYZQPYaC2lq1kTIEOlUfZZvMy5lxVPVZ8y2
|
|
||||||
foit+0DewZsqLDJwbjZ3wYMERVEY7KagoInQa3A1ZC9SkFiCb4fNEbRF13gfjrSz
|
|
||||||
muRbKAhEhkzJDFRocIaTKZPIWdvC73tAW66v1Zha74mxuckgnQPPqQ==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
@ -1 +0,0 @@
|
|||||||
passme
|
|
@ -1,45 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDvTCCAqWgAwIBAgIUOpY5wp7DtqsdxII7sxculedk0PYwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0yNDEyMzEwMDAwMDBaMG0xCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UE
|
|
||||||
AwwHUmV2b2tlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUu
|
|
||||||
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsksndW3LaWAnD7mi
|
|
||||||
4BXhmqQjC99Y9wTvMPUJ9AgvbzTaNW4JJOQ31x8VVgwoUQ8nFBYkAqgLOv9THzNi
|
|
||||||
30Fc7mjf37Pu6YsqZzql+tknqQbiaysyNm/fouwJDJ+NRzU70fVqI5AS9FBjakXa
|
|
||||||
/l1+pEysCofURJAcKCBQGMSVaP2gwVrHyPI7snFPO6205vqaEOarPira7gvBkYeU
|
|
||||||
Gh+A4AHngyW/jXHt0OHzmL+NrJe5hiayNHAK4ECfXj4PbMibI8PHlRpQkkzO6OhC
|
|
||||||
uI5ngpTZ0dGDLT693tlusvWRFjVrHI1D6MGTtQeeVlnYIKSEGhkgzp7PeWM/CCty
|
|
||||||
mDRG1wIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBQHE8SzT1ZcPEapv4NZ
|
|
||||||
MWBxRB3QATAfBgNVHSMEGDAWgBSeBawLW+FAf2oO9NlET4onfe84izATBgNVHSUE
|
|
||||||
DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAYVJiPrkACW/tK487fYS/
|
|
||||||
gYzU3fYVCTfHpAv3njarNzy8UBNqBYr0kDg0DLoOWqGV7ogTtlbQP4IIjAQI/kW6
|
|
||||||
cEreW8yU5VxO+kxDo+7oG9VEbR85i6kQW2ubJsXV6yBtf5aAbXEqImYrtjh7UObb
|
|
||||||
BbQiUI1ll2dXWqvZGxr3Fz1uz8nPMYlBpVjpCh6JF8otdWwABmxRnqUvoLO6BZbH
|
|
||||||
/gdUkouXfio9BlWkWaJXJGXMW8B7ozpjuCHSHyfvGKDA3YIfa7++A1BIKxW72jIF
|
|
||||||
jRJDw/rwnV59tiEcBWmp2T6vV+rD8yaS+LotRPYD/ck/jEj/mV+N077KLmuZpdJF
|
|
||||||
ag==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
Binary file not shown.
@ -1,50 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEzTCCA7WgAwIBAgIUfRjXKciCGA4XbhbhxbAwfpcLGmowDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xODAxMDEwMDAwMDBaFw0yODAxMDEwMDAwMDBaMFUxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxHDAaBgNVBAsME1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkxETAPBgNVBAMMCFRlc3QgVFNBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
|
||||||
AQ8AMIIBCgKCAQEAor220wp2zqj6Fe1VT/yic4LJcfMn1/ZWhsE7L86krULRvI+N
|
|
||||||
JY0fOVg/24MtyOXbnm7nYOyYTlR9n2kqm4fEgsz+GDQxXLHgyLh3aF4ueDzoFt0v
|
|
||||||
8G3vJfD+4N27XAYJ5V4f4s4VJRDIm0P/BvFGY9J/zICjC83F3OLdnkOD88O8QD6q
|
|
||||||
FwWdtBYNqxQX1LAwy3ORe5aTubdVkHV02JhdKAC/xy5nfhynuV4KfYyel2nHrI1i
|
|
||||||
54UXWdOrlD/XIKPiXpuEGcXhYTrTHigH+yR9ybs9hotGvuHTEjcxEuJvEQJX+qV4
|
|
||||||
eJAIexITDW/yK+maWPLijO3bZ9/JodX+fRCnPQIDAQABo4IBiDCCAYQwDAYDVR0T
|
|
||||||
AQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAdBgNVHQ4EFgQUKWCqogni
|
|
||||||
6SseJ/P6LXo0M2cK++QwHwYDVR0jBBgwFoAU/5nNuG4Tm4v2y9uKf428/4fVQesw
|
|
||||||
gYQGCCsGAQUFBwEBBHgwdjA5BggrBgEFBQcwAoYtaHR0cDovL1RTQUNBLnRpbWVz
|
|
||||||
dGFtcGF1dGhvcml0eS5jb20vVFNBQ0EuY3J0MDkGCCsGAQUFBzABhi1odHRwOi8v
|
|
||||||
b2NzcC5UU0FDQS50aW1lc3RhbXBhdXRob3JpdHkuY29tOjkwODAwPgYDVR0fBDcw
|
|
||||||
NTAzoDGgL4YtaHR0cDovL1RTQUNBLnRpbWVzdGFtcGF1dGhvcml0eS5jb20vVFNB
|
|
||||||
Q0EuY3JsMFUGA1UdHgROMEygGDAKggh0ZXN0LmNvbTAKggh0ZXN0Lm9yZ6EwMAqH
|
|
||||||
CAAAAAAAAAAAMCKHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA0G
|
|
||||||
CSqGSIb3DQEBCwUAA4IBAQB4YXa5nVWUzWSsUDMfYFTEETOe8boUErwfrDNBuj6z
|
|
||||||
B5en20FhI49i6PCYEfNq3vrAtPOEFJj+KPomN3C46VLxbUEvqWLdq6EyzWvVVmXK
|
|
||||||
VLeC0qV0m6CFM8GplaWzZdfFTQaaLUhgY08ZU2gp4QsoS2YjAosxlZrNSm6pBbv3
|
|
||||||
q+Og1KeSK8gKS0V89k+6e3LOEF6KaNWKSkoz5xDniQY//mTjiDcNmYUh0KhHfhdU
|
|
||||||
eO92M82uJSaDqnRs5HsWPs6z6qdfpuvj++OtQ1VCM2p5SEH2sEomdeN3YYChuG4h
|
|
||||||
yzn0mYAdbTyGJHlFm17AH+SQRbVqCKYdHDaqsMb+fWzi
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDkDCCAnigAwIBAgIUJ0nfE+EVsIThltlY2LHVWMJVIq4wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xNzAxMDEwMDAwMDBaFw0yNjExMTAwMDAwMDBaMGAxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxJDAiBgNVBAsMG1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkgUm9vdCBDQTEUMBIGA1UEAwwLVFNBIFJvb3QgQ0EwggEiMA0GCSqG
|
|
||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGOTX1f9dmtUiyzlsUInRIGfRMya338SVx
|
|
||||||
vYGeOwdpTSSGlYUVwR9AuFewQF5+klelstCJe+SoUG0AdzS30mRWlQrhip4UdvdW
|
|
||||||
T2gkNKbSn6DQzlWoQej9izqRLxAsbuszgkvnLOBEmPaLimDsCgu0bAN95Hp0Hls9
|
|
||||||
O/fVmzh8VuV4iscxc7q13ZB7CylWgwd55CFEGd/jpJ6kMwSHbOLoBWp4GQ3KxR+c
|
|
||||||
ASAo0FapU2WSZB2EYWszRiyq91X+AvIYN4ypTv7RccgfUvnZ2qFykJAkf/wgkynu
|
|
||||||
Qg7rCUNfUEpDc7jlqtDWR7iLrtHBkA17C3IU8ymmKQYWfw3ZyBwvAgMBAAGjQjBA
|
|
||||||
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP+ZzbhuE5uL9svbin+NvP+H1UHr
|
|
||||||
MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAbj3aFwIUxvzwgywO
|
|
||||||
gj01JM8GNbw1E4MGdkaNI8rgeY8ay15ZXhR9NpRWWb6Y7IXPq5XhuEktVte5Z4Kf
|
|
||||||
XLBrr7Xe9VVqJL9zd1tMzOEM/zG77rZf/iXBTZLkCtQc/GOEY4TTWKNEl5hiWVE0
|
|
||||||
po97GX5XHoeyHlWQ75sd9z6MxFxmvdp9/uyYD700e9sd5gcD8LGvHw2DNy8vntYV
|
|
||||||
ia9h95N9i1umffxU460o8W5GoIcsD13B3YftvnWhGSXqovBRFgcPAQZ4eW9Qh/zA
|
|
||||||
4zQBQrRvmREPihXVdgtWVpbRchP99oSZBrYr7Hh/P69rycklquqxJl1ol1wbT6dK
|
|
||||||
S5Gmng==
|
|
||||||
-----END CERTIFICATE-----
|
|
40
tests/check_cryptography.py
Normal file
40
tests/check_cryptography.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Check cryptography module."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cryptography
|
||||||
|
print(cryptography.__version__, end="")
|
||||||
|
except ModuleNotFoundError as ierr:
|
||||||
|
print("Module not installed: {}".format(ierr))
|
||||||
|
sys.exit(1)
|
||||||
|
except ImportError as ierr:
|
||||||
|
print("Module not found: {}".format(ierr))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
class UnsupportedVersion(Exception):
|
||||||
|
"""Unsupported version"""
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Check python3-cryptography version"""
|
||||||
|
try:
|
||||||
|
version = tuple(int(num) for num in cryptography.__version__.split('.'))
|
||||||
|
if version < (37, 0, 2):
|
||||||
|
raise UnsupportedVersion("unsupported python3-cryptography version")
|
||||||
|
except UnsupportedVersion as err:
|
||||||
|
print(" {}".format(err), end="")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
51
tests/client_http.py
Normal file
51
tests/client_http.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Implementation of a HTTP client"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import http.client
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Creating a POST Request"""
|
||||||
|
ret = 0
|
||||||
|
try:
|
||||||
|
file_path = os.path.join(RESULT_PATH, "./Testing/logs/url.log")
|
||||||
|
with open(file_path, mode="r", encoding="utf-8") as file:
|
||||||
|
url = file.readline()
|
||||||
|
host, port = url.split(":")
|
||||||
|
conn = http.client.HTTPConnection(host, port)
|
||||||
|
conn.request('POST', '/kill_server')
|
||||||
|
response = conn.getresponse()
|
||||||
|
print("HTTP status code:", response.getcode(), end=', ')
|
||||||
|
try:
|
||||||
|
text = response.read()
|
||||||
|
print(text.decode("UTF-8"), end='', flush=True)
|
||||||
|
except OSError as err:
|
||||||
|
print(f"Warning: {err}")
|
||||||
|
conn.close()
|
||||||
|
except OSError as err:
|
||||||
|
print(f"OSError: {err}")
|
||||||
|
ret = err.errno
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print(f"HTTP client error: {err}")
|
||||||
|
ret = err
|
||||||
|
finally:
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
@ -1,260 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
result=0
|
|
||||||
|
|
||||||
test_result() {
|
|
||||||
if test "$1" -eq 0
|
|
||||||
then
|
|
||||||
printf "Succeeded\n" >> "makecerts.log"
|
|
||||||
else
|
|
||||||
printf "Failed\n" >> "makecerts.log"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
make_certs() {
|
|
||||||
password=passme
|
|
||||||
result_path=$(pwd)
|
|
||||||
cd $(dirname "$0")
|
|
||||||
script_path=$(pwd)
|
|
||||||
cd "${result_path}"
|
|
||||||
mkdir "tmp/"
|
|
||||||
rm -rf "../certs"
|
|
||||||
|
|
||||||
# OpenSSL settings
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
if test -n "$1"
|
|
||||||
then
|
|
||||||
OPENSSL="$1/bin/openssl"
|
|
||||||
export LD_LIBRARY_PATH="$1/lib:$1/lib64"
|
|
||||||
else
|
|
||||||
OPENSSL=openssl
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir "CA/" 2>> "makecerts.log" 1>&2
|
|
||||||
touch "CA/index.txt"
|
|
||||||
echo -n "unique_subject = no" > "CA/index.txt.attr"
|
|
||||||
$OPENSSL rand -hex 16 > "CA/serial"
|
|
||||||
$OPENSSL rand -hex 16 > "tsa-serial"
|
|
||||||
echo 1001 > "CA/crlnumber"
|
|
||||||
date > "makecerts.log"
|
|
||||||
"$OPENSSL" version 2>> "makecerts.log" 1>&2
|
|
||||||
echo -n "$password" > tmp/password.txt
|
|
||||||
|
|
||||||
printf "\nGenerate root CA certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/CA.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_root.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 3600 -key CA/CA.key -out tmp/CACert.pem \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Root CA" \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate intermediate CA certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/intermediate.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/intermediate.key -out CA/intermediate.csr \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Intermediate CA" \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_root.cnf"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/intermediate.csr -out CA/intermediate.cer \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/intermediate.cer -out tmp/intermediate.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate private RSA encrypted key\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -des3 -out CA/private.key -passout pass:"$password" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
cat CA/private.key >> tmp/keyp.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate private RSA decrypted key\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" rsa -in CA/private.key -passin pass:"$password" -out tmp/key.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate a certificate to revoke\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/revoked.csr \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=CSP/CN=Revoked/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/revoked.csr -out CA/revoked.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/revoked.cer -out tmp/revoked.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nRevoke above certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -revoke CA/revoked.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nAttach intermediate certificate to revoked certificate\n" >> "makecerts.log"
|
|
||||||
cat tmp/intermediate.pem >> tmp/revoked.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate CRL file\n" >> "makecerts.log"
|
|
||||||
TZ=GMT faketime -f '@2019-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -gencrl -crldays 8766 -out tmp/CACertCRL.pem \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert revoked certificate to SPC format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" crl2pkcs7 -in tmp/CACertCRL.pem -certfile tmp/revoked.pem -outform DER -out tmp/revoked.spc \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate CSP Cross-Certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/cross.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
TZ=GMT faketime -f '@2018-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 900 -key CA/cross.key -out tmp/crosscert.pem \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=CSP/CN=crosscert/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate code signing certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/cert.csr \
|
|
||||||
-subj "/C=PL/ST=Mazovia Province/L=Warsaw/O=osslsigncode/OU=CSP/CN=Certificate/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/cert.csr -out CA/cert.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/cert.cer -out tmp/cert.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the key to DER format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" rsa -in tmp/key.pem -outform DER -out tmp/key.der -passout pass:"$password" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the key to PVK format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" rsa -in tmp/key.pem -outform PVK -out tmp/key.pvk -pvk-none \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the certificate to DER format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" x509 -in tmp/cert.pem -outform DER -out tmp/cert.der \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nAttach intermediate certificate to code signing certificate\n" >> "makecerts.log"
|
|
||||||
cat tmp/intermediate.pem >> tmp/cert.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the certificate to SPC format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" crl2pkcs7 -nocrl -certfile tmp/cert.pem -outform DER -out tmp/cert.spc \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the certificate and the key into a PKCS#12 container\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" pkcs12 -export -in tmp/cert.pem -inkey tmp/key.pem -out tmp/cert.p12 -passout pass:"$password" \
|
|
||||||
-keypbe aes-256-cbc -certpbe aes-256-cbc \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate expired certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/expired.csr \
|
|
||||||
-subj "/C=PL/ST=Mazovia Province/L=Warsaw/O=osslsigncode/OU=CSP/CN=Expired/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" ca -config "$CONF" -enddate "190101000000Z" -batch -in CA/expired.csr -out CA/expired.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/expired.cer -out tmp/expired.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nAttach intermediate certificate to expired certificate\n" >> "makecerts.log"
|
|
||||||
cat tmp/intermediate.pem >> tmp/expired.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate Root CA TSA certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/TSACA.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_tsa_root.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 3600 -key CA/TSACA.key -out tmp/TSACA.pem \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate TSA certificate\n" >> "makecerts.log"
|
|
||||||
CONF="${script_path}/openssl_tsa.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -nodes -keyout tmp/TSA.key -out CA/TSA.csr \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
CONF="${script_path}/openssl_tsa_root.cnf"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/TSA.csr -out CA/TSA.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/TSA.cer -out tmp/TSA.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nSave the chain to be included in the TSA response\n" >> "makecerts.log"
|
|
||||||
cat tmp/TSA.pem tmp/TSACA.pem > tmp/tsa-chain.pem 2>> "makecerts.log"
|
|
||||||
|
|
||||||
# copy new files
|
|
||||||
if test -s tmp/intermediate.pem -a -s tmp/CACert.pem -a -s tmp/CACertCRL.pem \
|
|
||||||
-a -s tmp/key.pem -a -s tmp/keyp.pem -a -s tmp/key.der -a -s tmp/key.pvk \
|
|
||||||
-a -s tmp/cert.pem -a -s tmp/cert.p12 -a -s tmp/cert.der -a -s tmp/cert.spc \
|
|
||||||
-a -s tmp/crosscert.pem -a -s tmp/expired.pem -a -s tmp/revoked.pem -a -s tmp/revoked.spc \
|
|
||||||
-a -s tmp/TSA.pem -a -s tmp/TSA.key -a -s tmp/tsa-chain.pem
|
|
||||||
then
|
|
||||||
mkdir "../certs"
|
|
||||||
cp tmp/* ../certs
|
|
||||||
printf "%s" "keys & certificates successfully generated"
|
|
||||||
else
|
|
||||||
printf "%s" "error logs ${result_path}/makecerts.log"
|
|
||||||
result=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# remove the working directory
|
|
||||||
rm -rf "CA/"
|
|
||||||
rm -rf "tmp/"
|
|
||||||
|
|
||||||
exit "$result"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Tests requirement
|
|
||||||
if test -n "$(command -v faketime)"
|
|
||||||
then
|
|
||||||
make_certs "$1"
|
|
||||||
result=$?
|
|
||||||
else
|
|
||||||
printf "%s" "faketime not found in \$PATH, please install faketime package"
|
|
||||||
result=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit "$result"
|
|
@ -1,72 +0,0 @@
|
|||||||
# OpenSSL intermediate CA configuration file
|
|
||||||
|
|
||||||
[ default ]
|
|
||||||
name = intermediate
|
|
||||||
default_ca = CA_default
|
|
||||||
|
|
||||||
[ CA_default ]
|
|
||||||
# Directory and file locations
|
|
||||||
dir = .
|
|
||||||
certs = $dir/CA
|
|
||||||
crl_dir = $dir/CA
|
|
||||||
new_certs_dir = $dir/CA
|
|
||||||
database = $dir/CA/index.txt
|
|
||||||
serial = $dir/CA/serial
|
|
||||||
rand_serial = yes
|
|
||||||
private_key = $dir/CA/$name.key
|
|
||||||
certificate = $dir/tmp/$name.pem
|
|
||||||
crl_extensions = crl_ext
|
|
||||||
default_md = sha256
|
|
||||||
preserve = no
|
|
||||||
policy = policy_loose
|
|
||||||
default_startdate = 180101000000Z
|
|
||||||
default_enddate = 241231000000Z
|
|
||||||
x509_extensions = v3_req
|
|
||||||
email_in_dn = yes
|
|
||||||
default_days = 2200
|
|
||||||
|
|
||||||
[ req ]
|
|
||||||
# Options for the `req` tool
|
|
||||||
encrypt_key = no
|
|
||||||
default_bits = 2048
|
|
||||||
default_md = sha256
|
|
||||||
string_mask = utf8only
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
x509_extensions = usr_extensions
|
|
||||||
|
|
||||||
[ crl_ext ]
|
|
||||||
# Extension for CRLs
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
|
|
||||||
[ usr_extensions ]
|
|
||||||
# Extension to add when the -x509 option is used
|
|
||||||
basicConstraints = CA:FALSE
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid, issuer
|
|
||||||
extendedKeyUsage = codeSigning
|
|
||||||
|
|
||||||
[ v3_req ]
|
|
||||||
basicConstraints = CA:FALSE
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid, issuer
|
|
||||||
extendedKeyUsage = codeSigning
|
|
||||||
|
|
||||||
[ policy_loose ]
|
|
||||||
# Allow the intermediate CA to sign a more diverse range of certificates.
|
|
||||||
# See the POLICY FORMAT section of the `ca` man page.
|
|
||||||
countryName = optional
|
|
||||||
stateOrProvinceName = optional
|
|
||||||
localityName = optional
|
|
||||||
organizationName = optional
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = Country Name (2 letter code)
|
|
||||||
stateOrProvinceName = State or Province Name
|
|
||||||
localityName = Locality Name
|
|
||||||
0.organizationName = Organization Name
|
|
||||||
organizationalUnitName = Organizational Unit Name
|
|
||||||
commonName = Common Name
|
|
||||||
emailAddress = Email Address
|
|
@ -1,65 +0,0 @@
|
|||||||
# OpenSSL root CA configuration file
|
|
||||||
|
|
||||||
[ ca ]
|
|
||||||
default_ca = CA_default
|
|
||||||
|
|
||||||
[ CA_default ]
|
|
||||||
# Directory and file locations.
|
|
||||||
dir = .
|
|
||||||
certs = $dir/CA
|
|
||||||
crl_dir = $dir/CA
|
|
||||||
new_certs_dir = $dir/CA
|
|
||||||
database = $dir/CA/index.txt
|
|
||||||
serial = $dir/CA/serial
|
|
||||||
rand_serial = yes
|
|
||||||
private_key = $dir/CA/CA.key
|
|
||||||
certificate = $dir/tmp/CACert.pem
|
|
||||||
crl_extensions = crl_ext
|
|
||||||
default_md = sha256
|
|
||||||
preserve = no
|
|
||||||
policy = policy_match
|
|
||||||
default_startdate = 180101000000Z
|
|
||||||
default_enddate = 260101000000Z
|
|
||||||
x509_extensions = v3_intermediate_ca
|
|
||||||
email_in_dn = yes
|
|
||||||
default_days = 3000
|
|
||||||
unique_subject = no
|
|
||||||
|
|
||||||
[ req ]
|
|
||||||
# Options for the `req` tool
|
|
||||||
encrypt_key = no
|
|
||||||
default_bits = 2048
|
|
||||||
default_md = sha256
|
|
||||||
string_mask = utf8only
|
|
||||||
x509_extensions = ca_extensions
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
|
|
||||||
[ ca_extensions ]
|
|
||||||
# Extension to add when the -x509 option is used
|
|
||||||
basicConstraints = critical, CA:true
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always,issuer
|
|
||||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
||||||
|
|
||||||
[ v3_intermediate_ca ]
|
|
||||||
# Extensions for a typical intermediate CA (`man x509v3_config`)
|
|
||||||
basicConstraints = critical, CA:true, pathlen:0
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always,issuer
|
|
||||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
||||||
|
|
||||||
[ policy_match ]
|
|
||||||
countryName = match
|
|
||||||
organizationName = match
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = Country Name (2 letter code)
|
|
||||||
stateOrProvinceName = State or Province Name
|
|
||||||
localityName = Locality Name
|
|
||||||
0.organizationName = Organization Name
|
|
||||||
organizationalUnitName = Organizational Unit Name
|
|
||||||
commonName = Common Name
|
|
||||||
emailAddress = Email Address
|
|
@ -44,3 +44,4 @@ ordering = yes
|
|||||||
tsa_name = yes
|
tsa_name = yes
|
||||||
ess_cert_id_chain = yes
|
ess_cert_id_chain = yes
|
||||||
ess_cert_id_alg = sha256
|
ess_cert_id_alg = sha256
|
||||||
|
crypto_device = builtin
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
# OpenSSL Root Timestamp Authority configuration file
|
|
||||||
|
|
||||||
[ default ]
|
|
||||||
name = TSACA
|
|
||||||
domain_suffix = timestampauthority.com
|
|
||||||
aia_url = http://$name.$domain_suffix/$name.crt
|
|
||||||
crl_url = http://$name.$domain_suffix/$name.crl
|
|
||||||
ocsp_url = http://ocsp.$name.$domain_suffix:9080
|
|
||||||
name_opt = utf8, esc_ctrl, multiline, lname, align
|
|
||||||
default_ca = CA_default
|
|
||||||
|
|
||||||
[ CA_default ]
|
|
||||||
dir = .
|
|
||||||
certs = $dir/CA
|
|
||||||
crl_dir = $dir/CA
|
|
||||||
new_certs_dir = $dir/CA
|
|
||||||
database = $dir/CA/index.txt
|
|
||||||
serial = $dir/CA/serial
|
|
||||||
crlnumber = $dir/CA/crlnumber
|
|
||||||
rand_serial = yes
|
|
||||||
private_key = $dir/CA/$name.key
|
|
||||||
certificate = $dir/tmp/$name.pem
|
|
||||||
default_md = sha256
|
|
||||||
default_days = 3650
|
|
||||||
default_crl_days = 365
|
|
||||||
policy = policy_match
|
|
||||||
default_startdate = 20180101000000Z
|
|
||||||
default_enddate = 20280101000000Z
|
|
||||||
unique_subject = no
|
|
||||||
x509_extensions = tsa_extensions
|
|
||||||
|
|
||||||
[ policy_match ]
|
|
||||||
countryName = match
|
|
||||||
stateOrProvinceName = optional
|
|
||||||
organizationName = match
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[ tsa_extensions ]
|
|
||||||
basicConstraints = critical, CA:false
|
|
||||||
extendedKeyUsage = critical, timeStamping
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
authorityInfoAccess = @issuer_info
|
|
||||||
crlDistributionPoints = @crl_info
|
|
||||||
nameConstraints = @name_constraints
|
|
||||||
|
|
||||||
[ issuer_info ]
|
|
||||||
caIssuers;URI.0 = $aia_url
|
|
||||||
OCSP;URI.0 = $ocsp_url
|
|
||||||
|
|
||||||
[ crl_info ]
|
|
||||||
URI.0 = $crl_url
|
|
||||||
|
|
||||||
[ name_constraints ]
|
|
||||||
permitted;DNS.0=test.com
|
|
||||||
permitted;DNS.1=test.org
|
|
||||||
excluded;IP.0=0.0.0.0/0.0.0.0
|
|
||||||
excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0
|
|
||||||
|
|
||||||
[ req ]
|
|
||||||
# Options for the `req` tool
|
|
||||||
default_bits = 2048
|
|
||||||
encrypt_key = yes
|
|
||||||
default_md = sha256
|
|
||||||
utf8 = yes
|
|
||||||
string_mask = utf8only
|
|
||||||
prompt = no
|
|
||||||
distinguished_name = ca_distinguished_name
|
|
||||||
x509_extensions = ca_extensions
|
|
||||||
|
|
||||||
[ ca_distinguished_name ]
|
|
||||||
countryName = "PL"
|
|
||||||
organizationName = "osslsigncode"
|
|
||||||
organizationalUnitName = "Timestamp Authority Root CA"
|
|
||||||
commonName = "TSA Root CA"
|
|
||||||
|
|
||||||
[ ca_extensions ]
|
|
||||||
# Extension to add when the -x509 option is used
|
|
||||||
basicConstraints = critical, CA:true
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
keyUsage = critical, keyCertSign, cRLSign
|
|
47
tests/exec.py
Normal file
47
tests/exec.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Implementation of a single ctest script."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
|
||||||
|
def parse(value):
|
||||||
|
"""Read parameter from file."""
|
||||||
|
prefix = 'FILE '
|
||||||
|
if value.startswith(prefix):
|
||||||
|
with open(value[len(prefix):], mode="r", encoding="utf-8") as file:
|
||||||
|
return file.read().strip()
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Run osslsigncode with its options."""
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
try:
|
||||||
|
params = map(parse, sys.argv[1:])
|
||||||
|
proc = Popen(params, stdout=PIPE, stderr=PIPE, text=True)
|
||||||
|
stdout, stderr = proc.communicate()
|
||||||
|
print(stdout, file=sys.stderr)
|
||||||
|
if stderr:
|
||||||
|
print("Error:\n" + "-" * 58 + "\n" + stderr, file=sys.stderr)
|
||||||
|
sys.exit(proc.returncode)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
# all exceptions are critical
|
||||||
|
print(err, file=sys.stderr)
|
||||||
|
else:
|
||||||
|
print("Usage:\n\t{} COMMAND [ARG]...'".format(sys.argv[0]), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
BIN
tests/files/unsigned.256appx
Normal file
BIN
tests/files/unsigned.256appx
Normal file
Binary file not shown.
BIN
tests/files/unsigned.512appx
Normal file
BIN
tests/files/unsigned.512appx
Normal file
Binary file not shown.
BIN
tests/files/unsigned.cat
Executable file → Normal file
BIN
tests/files/unsigned.cat
Executable file → Normal file
Binary file not shown.
0
tests/files/unsigned.exe
Executable file → Normal file
0
tests/files/unsigned.exe
Executable file → Normal file
BIN
tests/files/unsigned.mof
Normal file
BIN
tests/files/unsigned.mof
Normal file
Binary file not shown.
2
tests/files/unsigned.ps1
Normal file
2
tests/files/unsigned.ps1
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
cls
|
||||||
|
Write-Host "żółć"
|
5
tests/files/unsigned.psc1
Normal file
5
tests/files/unsigned.psc1
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PSConsoleFile ConsoleSchemaVersion="1.0">
|
||||||
|
<PSVersion>5.1.19041.3930</PSVersion>
|
||||||
|
<PSSnapIns />
|
||||||
|
</PSConsoleFile>
|
532
tests/make_certificates.py
Normal file
532
tests/make_certificates.py
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Make test certificates"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import cryptography
|
||||||
|
from cryptography import x509
|
||||||
|
from cryptography.x509.oid import NameOID
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.primitives import serialization
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
|
||||||
|
date_20170101 = datetime.datetime(2017, 1, 1)
|
||||||
|
date_20180101 = datetime.datetime(2018, 1, 1)
|
||||||
|
date_20190101 = datetime.datetime(2019, 1, 1)
|
||||||
|
|
||||||
|
PASSWORD='passme'
|
||||||
|
|
||||||
|
|
||||||
|
class X509Extensions():
|
||||||
|
"""Base class for X509 Extensions"""
|
||||||
|
|
||||||
|
def __init__(self, unit_name, cdp_port, cdp_name):
|
||||||
|
self.unit_name = unit_name
|
||||||
|
self.port = cdp_port
|
||||||
|
self.name = cdp_name
|
||||||
|
|
||||||
|
def create_x509_name(self, common_name) -> x509.Name:
|
||||||
|
"""Return x509.Name"""
|
||||||
|
return x509.Name(
|
||||||
|
[
|
||||||
|
x509.NameAttribute(NameOID.COUNTRY_NAME, "PL"),
|
||||||
|
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Mazovia Province"),
|
||||||
|
x509.NameAttribute(NameOID.LOCALITY_NAME, "Warsaw"),
|
||||||
|
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "osslsigncode"),
|
||||||
|
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, self.unit_name),
|
||||||
|
x509.NameAttribute(NameOID.COMMON_NAME, common_name)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_x509_crldp(self) -> x509.CRLDistributionPoints:
|
||||||
|
"""Return x509.CRLDistributionPoints"""
|
||||||
|
return x509.CRLDistributionPoints(
|
||||||
|
[
|
||||||
|
x509.DistributionPoint(
|
||||||
|
full_name=[x509.UniformResourceIdentifier(
|
||||||
|
"http://127.0.0.1:" + str(self.port) + "/" + str(self.name))
|
||||||
|
],
|
||||||
|
relative_name=None,
|
||||||
|
reasons=None,
|
||||||
|
crl_issuer=None
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_x509_name_constraints(self) -> x509.NameConstraints:
|
||||||
|
"""Return x509.NameConstraints"""
|
||||||
|
return x509.NameConstraints(
|
||||||
|
permitted_subtrees = [x509.DNSName('test.com'), x509.DNSName('test.org')],
|
||||||
|
excluded_subtrees = None
|
||||||
|
)
|
||||||
|
|
||||||
|
class IntermediateCACertificate(X509Extensions):
|
||||||
|
"""Base class for Intermediate CA certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key):
|
||||||
|
self.issuer_cert = issuer_cert
|
||||||
|
self.issuer_key = issuer_key
|
||||||
|
super().__init__("Certification Authority", 0, None)
|
||||||
|
|
||||||
|
def make_cert(self) -> (x509.Certificate, rsa.RSAPrivateKey):
|
||||||
|
"""Generate intermediate CA certificate"""
|
||||||
|
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
key_public = key.public_key()
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
key_usage = x509.KeyUsage(
|
||||||
|
digital_signature=True,
|
||||||
|
content_commitment=False,
|
||||||
|
key_encipherment=False,
|
||||||
|
data_encipherment=False,
|
||||||
|
key_agreement=False,
|
||||||
|
key_cert_sign=True,
|
||||||
|
crl_sign=True,
|
||||||
|
encipher_only=False,
|
||||||
|
decipher_only=False
|
||||||
|
)
|
||||||
|
cert = (
|
||||||
|
x509.CertificateBuilder()
|
||||||
|
.subject_name(self.create_x509_name("Intermediate CA"))
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.public_key(key_public)
|
||||||
|
.serial_number(x509.random_serial_number())
|
||||||
|
.not_valid_before(date_20180101)
|
||||||
|
.not_valid_after(date_20180101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(x509.BasicConstraints(ca=True, path_length=0), critical=True)
|
||||||
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(key_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(key_usage, critical=True)
|
||||||
|
.sign(self.issuer_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, "intermediateCA.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
return cert, key
|
||||||
|
|
||||||
|
|
||||||
|
class RootCACertificate(X509Extensions):
|
||||||
|
"""Base class for Root CA certificate"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.key_usage = x509.KeyUsage(
|
||||||
|
digital_signature=True,
|
||||||
|
content_commitment=False,
|
||||||
|
key_encipherment=False,
|
||||||
|
data_encipherment=False,
|
||||||
|
key_agreement=False,
|
||||||
|
key_cert_sign=True,
|
||||||
|
crl_sign=True,
|
||||||
|
encipher_only=False,
|
||||||
|
decipher_only=False
|
||||||
|
)
|
||||||
|
super().__init__("Certification Authority", 0, None)
|
||||||
|
|
||||||
|
def make_cert(self) -> (x509.Certificate, rsa.RSAPrivateKey):
|
||||||
|
"""Generate CA certificates"""
|
||||||
|
ca_root, root_key = self.make_ca_cert("Trusted Root CA", "CAroot.pem")
|
||||||
|
ca_cert, ca_key = self.make_ca_cert("Root CA", "CACert.pem")
|
||||||
|
self.make_cross_cert(ca_root, root_key, ca_cert, ca_key)
|
||||||
|
return ca_cert, ca_key
|
||||||
|
|
||||||
|
def make_ca_cert(self, common_name, file_name) -> None:
|
||||||
|
"""Generate self-signed root CA certificate"""
|
||||||
|
ca_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
ca_public = ca_key.public_key()
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_public_key(ca_public)
|
||||||
|
name = self.create_x509_name(common_name)
|
||||||
|
ca_cert = (
|
||||||
|
x509.CertificateBuilder()
|
||||||
|
.subject_name(name)
|
||||||
|
.issuer_name(name)
|
||||||
|
.public_key(ca_public)
|
||||||
|
.serial_number(x509.random_serial_number())
|
||||||
|
.not_valid_before(date_20170101)
|
||||||
|
.not_valid_after(date_20170101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
|
||||||
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(self.key_usage, critical=True)
|
||||||
|
.sign(ca_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, file_name)
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(ca_cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
return ca_cert, ca_key
|
||||||
|
|
||||||
|
def make_cross_cert(self, ca_root, root_key, ca_cert, ca_key) -> None:
|
||||||
|
"""Generate cross-signed root CA certificate"""
|
||||||
|
ca_public = ca_key.public_key()
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
ca_root.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
ca_cross = (
|
||||||
|
x509.CertificateBuilder()
|
||||||
|
.subject_name(ca_cert.subject)
|
||||||
|
.issuer_name(ca_root.subject)
|
||||||
|
.public_key(ca_public)
|
||||||
|
.serial_number(ca_cert.serial_number)
|
||||||
|
.not_valid_before(date_20180101)
|
||||||
|
.not_valid_after(date_20180101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
|
||||||
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(self.key_usage, critical=True)
|
||||||
|
.sign(root_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, "CAcross.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(ca_cross.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
def write_key(self, key, file_name) -> None:
|
||||||
|
"""Write a private RSA key"""
|
||||||
|
# Write password
|
||||||
|
file_path = os.path.join(CERTS_PATH, "password.txt")
|
||||||
|
with open(file_path, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("{}".format(PASSWORD))
|
||||||
|
|
||||||
|
# Write encrypted key in PEM format
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + "p.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=serialization.BestAvailableEncryption(PASSWORD.encode())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Write decrypted key in PEM format
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=serialization.NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Write the key in DER format
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".der")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=serialization.Encoding.DER,
|
||||||
|
format=serialization.PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=serialization.NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TSARootCACertificate(X509Extensions):
|
||||||
|
"""Base class for TSA certificates"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Timestamp Authority Root CA", 0, None)
|
||||||
|
|
||||||
|
def make_cert(self) -> (x509.Certificate, rsa.RSAPrivateKey):
|
||||||
|
"""Generate a Time Stamp Authority certificate"""
|
||||||
|
ca_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
ca_public = ca_key.public_key()
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_public_key(ca_public)
|
||||||
|
name = self.create_x509_name("TSA Root CA")
|
||||||
|
key_usage = x509.KeyUsage(
|
||||||
|
digital_signature=False,
|
||||||
|
content_commitment=False,
|
||||||
|
key_encipherment=False,
|
||||||
|
data_encipherment=False,
|
||||||
|
key_agreement=False,
|
||||||
|
key_cert_sign=True,
|
||||||
|
crl_sign=True,
|
||||||
|
encipher_only=False,
|
||||||
|
decipher_only=False
|
||||||
|
)
|
||||||
|
ca_cert = (
|
||||||
|
x509.CertificateBuilder()
|
||||||
|
.subject_name(name)
|
||||||
|
.issuer_name(name)
|
||||||
|
.public_key(ca_public)
|
||||||
|
.serial_number(x509.random_serial_number())
|
||||||
|
.not_valid_before(date_20170101)
|
||||||
|
.not_valid_after(date_20170101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
|
||||||
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(key_usage, critical=True)
|
||||||
|
.sign(ca_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, "TSACA.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(ca_cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
return ca_cert, ca_key
|
||||||
|
|
||||||
|
def write_key(self, key, file_name) -> None:
|
||||||
|
"""Write decrypted private RSA key into PEM format"""
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".key")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=serialization.Encoding.PEM,
|
||||||
|
format=serialization.PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=serialization.NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Certificate(X509Extensions):
|
||||||
|
"""Base class for a leaf certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key, unit_name, common_name, cdp_port, cdp_name):
|
||||||
|
#pylint: disable=too-many-arguments
|
||||||
|
self.issuer_cert = issuer_cert
|
||||||
|
self.issuer_key = issuer_key
|
||||||
|
self.common_name = common_name
|
||||||
|
super().__init__(unit_name, cdp_port, cdp_name)
|
||||||
|
|
||||||
|
def make_cert(self, public_key, not_before, days) -> x509.Certificate:
|
||||||
|
"""Generate a leaf certificate"""
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
extended_key_usage = x509.ExtendedKeyUsage(
|
||||||
|
[x509.oid.ExtendedKeyUsageOID.CODE_SIGNING]
|
||||||
|
)
|
||||||
|
cert = (
|
||||||
|
x509.CertificateBuilder()
|
||||||
|
.subject_name(self.create_x509_name(self.common_name))
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.public_key(public_key)
|
||||||
|
.serial_number(x509.random_serial_number())
|
||||||
|
.not_valid_before(not_before)
|
||||||
|
.not_valid_after(not_before + datetime.timedelta(days=days))
|
||||||
|
.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=False)
|
||||||
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(public_key), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(extended_key_usage, critical=False)
|
||||||
|
.add_extension(self.create_x509_crldp(), critical=False)
|
||||||
|
.sign(self.issuer_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
# Write PEM file and attach intermediate certificate
|
||||||
|
file_path = os.path.join(CERTS_PATH, self.common_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
file.write(self.issuer_cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
return cert
|
||||||
|
|
||||||
|
def revoke_cert(self, serial_number, file_name) -> None:
|
||||||
|
"""Revoke a certificate"""
|
||||||
|
revoked = (
|
||||||
|
x509.RevokedCertificateBuilder()
|
||||||
|
.serial_number(serial_number)
|
||||||
|
.revocation_date(date_20190101)
|
||||||
|
.add_extension(x509.CRLReason(x509.ReasonFlags.superseded), critical=False)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
# Generate CRL
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
crl = (
|
||||||
|
x509.CertificateRevocationListBuilder()
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.last_update(date_20190101)
|
||||||
|
.next_update(date_20190101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(x509.CRLNumber(4097), critical=False)
|
||||||
|
.add_revoked_certificate(revoked)
|
||||||
|
.sign(self.issuer_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
# Write CRL file
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(crl.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".der")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(crl.public_bytes(encoding=serialization.Encoding.DER))
|
||||||
|
|
||||||
|
|
||||||
|
class LeafCACertificate(Certificate):
|
||||||
|
"""Base class for a leaf certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key, common, cdp_port):
|
||||||
|
super().__init__(issuer_cert, issuer_key, "CSP", common, cdp_port, "intermediateCA")
|
||||||
|
|
||||||
|
|
||||||
|
class LeafTSACertificate(Certificate):
|
||||||
|
"""Base class for a TSA leaf certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key, common, cdp_port):
|
||||||
|
self.issuer_cert = issuer_cert
|
||||||
|
self.issuer_key = issuer_key
|
||||||
|
self.common_name = common
|
||||||
|
super().__init__(issuer_cert, issuer_key, "Timestamp Root CA", common, cdp_port, "TSACA")
|
||||||
|
|
||||||
|
def make_cert(self, public_key, not_before, days) -> x509.Certificate:
|
||||||
|
"""Generate a TSA leaf certificate"""
|
||||||
|
|
||||||
|
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
|
||||||
|
# The TSA signing certificate must have exactly one extended key usage
|
||||||
|
# assigned to it: timeStamping. The extended key usage must also be critical,
|
||||||
|
# otherwise the certificate is going to be refused.
|
||||||
|
extended_key_usage = x509.ExtendedKeyUsage(
|
||||||
|
[x509.oid.ExtendedKeyUsageOID.TIME_STAMPING]
|
||||||
|
)
|
||||||
|
cert = (
|
||||||
|
x509.CertificateBuilder()
|
||||||
|
.subject_name(self.create_x509_name(self.common_name))
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.public_key(public_key)
|
||||||
|
.serial_number(x509.random_serial_number())
|
||||||
|
.not_valid_before(not_before)
|
||||||
|
.not_valid_after(not_before + datetime.timedelta(days=days))
|
||||||
|
.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True)
|
||||||
|
.add_extension(x509.SubjectKeyIdentifier.from_public_key(public_key), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(extended_key_usage, critical=True)
|
||||||
|
.add_extension(self.create_x509_crldp(), critical=False)
|
||||||
|
.add_extension(self.create_x509_name_constraints(), critical=False)
|
||||||
|
.sign(self.issuer_key, hashes.SHA256())
|
||||||
|
)
|
||||||
|
# Write PEM file and attach intermediate certificate
|
||||||
|
file_path = os.path.join(CERTS_PATH, self.common_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
file.write(self.issuer_cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
return cert
|
||||||
|
|
||||||
|
|
||||||
|
class CertificateMaker():
|
||||||
|
"""Base class for test certificates"""
|
||||||
|
|
||||||
|
def __init__(self, cdp_port, logs):
|
||||||
|
self.cdp_port = cdp_port
|
||||||
|
self.logs = logs
|
||||||
|
|
||||||
|
def make_certs(self) -> None:
|
||||||
|
"""Make test certificates"""
|
||||||
|
try:
|
||||||
|
self.make_ca_certs()
|
||||||
|
self.make_tsa_certs()
|
||||||
|
logs = os.path.join(CERTS_PATH, "./cert.log")
|
||||||
|
with open(logs, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("Test certificates generation succeeded")
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
with open(self.logs, mode="a", encoding="utf-8") as file:
|
||||||
|
file.write("Error: {}".format(err))
|
||||||
|
|
||||||
|
def make_ca_certs(self):
|
||||||
|
"""Make test certificates"""
|
||||||
|
|
||||||
|
# Generate root CA certificate
|
||||||
|
root = RootCACertificate()
|
||||||
|
ca_cert, ca_key = root.make_cert()
|
||||||
|
|
||||||
|
# Generate intermediate root CA certificate
|
||||||
|
intermediate = IntermediateCACertificate(ca_cert, ca_key)
|
||||||
|
issuer_cert, issuer_key = intermediate.make_cert()
|
||||||
|
|
||||||
|
# Generate private RSA key
|
||||||
|
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
root.write_key(key=private_key, file_name="key")
|
||||||
|
|
||||||
|
# Generate expired certificate
|
||||||
|
expired = LeafCACertificate(issuer_cert, issuer_key, "expired", self.cdp_port)
|
||||||
|
expired.make_cert(public_key, date_20180101, 365)
|
||||||
|
|
||||||
|
# Generate revoked certificate
|
||||||
|
revoked = LeafCACertificate(issuer_cert, issuer_key, "revoked", self.cdp_port)
|
||||||
|
cert = revoked.make_cert(public_key, date_20180101, 5840)
|
||||||
|
revoked.revoke_cert(cert.serial_number, "CACertCRL")
|
||||||
|
|
||||||
|
# Generate code signing certificate
|
||||||
|
signer = LeafCACertificate(issuer_cert, issuer_key, "cert", self.cdp_port)
|
||||||
|
cert = signer.make_cert(public_key, date_20180101, 5840)
|
||||||
|
|
||||||
|
# Write a certificate and a key into PKCS#12 container
|
||||||
|
self.write_pkcs12_container(
|
||||||
|
cert=cert,
|
||||||
|
key=private_key,
|
||||||
|
issuer=issuer_cert
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write DER file and attach intermediate certificate
|
||||||
|
file_path = os.path.join(CERTS_PATH, "cert.der")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=serialization.Encoding.DER))
|
||||||
|
|
||||||
|
def make_tsa_certs(self):
|
||||||
|
"""Make test TSA certificates"""
|
||||||
|
|
||||||
|
# Time Stamp Authority certificate
|
||||||
|
root = TSARootCACertificate()
|
||||||
|
issuer_cert, issuer_key = root.make_cert()
|
||||||
|
|
||||||
|
# Generate private RSA key
|
||||||
|
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
root.write_key(key=private_key, file_name="TSA")
|
||||||
|
|
||||||
|
# Generate revoked TSA certificate
|
||||||
|
revoked = LeafTSACertificate(issuer_cert, issuer_key, "TSA_revoked", self.cdp_port)
|
||||||
|
cert = revoked.make_cert(public_key, date_20180101, 7300)
|
||||||
|
revoked.revoke_cert(cert.serial_number, "TSACertCRL")
|
||||||
|
|
||||||
|
# Generate TSA certificate
|
||||||
|
signer = LeafTSACertificate(issuer_cert, issuer_key, "TSA", self.cdp_port)
|
||||||
|
cert = signer.make_cert(public_key, date_20180101, 7300)
|
||||||
|
|
||||||
|
# Save the chain to be included in the TSA response
|
||||||
|
file_path = os.path.join(CERTS_PATH, "tsa-chain.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
file.write(issuer_cert.public_bytes(encoding=serialization.Encoding.PEM))
|
||||||
|
|
||||||
|
|
||||||
|
def write_pkcs12_container(self, cert, key, issuer) -> None:
|
||||||
|
"""Write a certificate and a key into a PKCS#12 container"""
|
||||||
|
|
||||||
|
# Set an encryption algorithm
|
||||||
|
if cryptography.__version__ >= "38.0.0":
|
||||||
|
# For OpenSSL legacy mode use the default algorithm for certificate
|
||||||
|
# and private key encryption: DES-EDE3-CBC (vel 3DES_CBC)
|
||||||
|
# pylint: disable=no-member
|
||||||
|
encryption = (
|
||||||
|
serialization.PrivateFormat.PKCS12.encryption_builder()
|
||||||
|
.key_cert_algorithm(serialization.pkcs12.PBES.PBESv1SHA1And3KeyTripleDESCBC)
|
||||||
|
.kdf_rounds(5000)
|
||||||
|
.build(PASSWORD.encode())
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
encryption = serialization.BestAvailableEncryption(PASSWORD.encode())
|
||||||
|
|
||||||
|
# Generate PKCS#12 struct
|
||||||
|
pkcs12 = serialization.pkcs12.serialize_key_and_certificates(
|
||||||
|
name=b'certificate',
|
||||||
|
key=key,
|
||||||
|
cert=cert,
|
||||||
|
cas=(issuer,),
|
||||||
|
encryption_algorithm=encryption
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write into a PKCS#12 container
|
||||||
|
file_path = os.path.join(CERTS_PATH, "cert.p12")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(pkcs12)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
175
tests/server_http.py
Normal file
175
tests/server_http.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Implementation of a HTTP server"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from http.server import SimpleHTTPRequestHandler, HTTPServer
|
||||||
|
from socketserver import ThreadingMixIn
|
||||||
|
from make_certificates import CertificateMaker
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
CONF_PATH = os.path.join(RESULT_PATH, "./Testing/conf/")
|
||||||
|
LOGS_PATH = os.path.join(RESULT_PATH, "./Testing/logs/")
|
||||||
|
REQUEST = os.path.join(FILES_PATH, "./jreq.tsq")
|
||||||
|
RESPONS = os.path.join(FILES_PATH, "./jresp.tsr")
|
||||||
|
OPENSSL_CONF = os.path.join(CONF_PATH, "./openssl_tsa.cnf")
|
||||||
|
SERVER_LOG = os.path.join(LOGS_PATH, "./server.log")
|
||||||
|
URL_LOG = os.path.join(LOGS_PATH, "./url.log")
|
||||||
|
|
||||||
|
OPENSSL_TS = ["openssl", "ts",
|
||||||
|
"-reply", "-config", OPENSSL_CONF,
|
||||||
|
"-passin", "pass:passme",
|
||||||
|
"-queryfile", REQUEST,
|
||||||
|
"-out", RESPONS]
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
|
"""This variant of HTTPServer creates a new thread for every connection"""
|
||||||
|
daemon_threads = True
|
||||||
|
|
||||||
|
|
||||||
|
class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
|
"""Handle the HTTP POST request that arrive at the server"""
|
||||||
|
|
||||||
|
def __init__(self, request, client_address, server):
|
||||||
|
# Save the server handle
|
||||||
|
self.server = server
|
||||||
|
SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
|
||||||
|
|
||||||
|
def do_GET(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the GET request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/pkix-crl")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
# Read the file and send the contents
|
||||||
|
if url.path == "/intermediateCA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./CACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
if url.path == "/TSACA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./TSACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP GET request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
def do_POST(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the POST request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
if url.path == "/kill_server":
|
||||||
|
self.log_message(f"Deleting file: {URL_LOG}")
|
||||||
|
os.remove(f"{URL_LOG}")
|
||||||
|
self.send_header('Content-type', 'text/plain')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(bytes('Shutting down HTTP server', 'utf-8'))
|
||||||
|
self.server.shutdown()
|
||||||
|
else:
|
||||||
|
content_length = int(self.headers['Content-Length'])
|
||||||
|
post_data = self.rfile.read(content_length)
|
||||||
|
with open(REQUEST, mode="wb") as file:
|
||||||
|
file.write(post_data)
|
||||||
|
openssl = subprocess.run(OPENSSL_TS, check=True, universal_newlines=True)
|
||||||
|
openssl.check_returncode()
|
||||||
|
self.send_header("Content-type", "application/timestamp-reply")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
with open(RESPONS, mode="rb") as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP POST request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
class HttpServerThread():
|
||||||
|
"""TSA server thread handler"""
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.server = None
|
||||||
|
self.server_thread = None
|
||||||
|
|
||||||
|
def start_server(self, port) -> (int):
|
||||||
|
"""Starting HTTP server on 127.0.0.1 and a random available port for binding"""
|
||||||
|
self.server = ThreadingHTTPServer(('127.0.0.1', port), RequestHandler)
|
||||||
|
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
||||||
|
self.server_thread.start()
|
||||||
|
hostname, port = self.server.server_address[:2]
|
||||||
|
print("HTTP server started, URL http://{}:{}".format(hostname, port))
|
||||||
|
return port
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Start HTTP server, make test certificates."""
|
||||||
|
|
||||||
|
ret = 0
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="port number"
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
server = HttpServerThread()
|
||||||
|
port = server.start_server(args.port)
|
||||||
|
with open(URL_LOG, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("127.0.0.1:{}".format(port))
|
||||||
|
tests = CertificateMaker(port, SERVER_LOG)
|
||||||
|
tests.make_certs()
|
||||||
|
except OSError as err:
|
||||||
|
print("OSError: {}".format(err))
|
||||||
|
ret = err.errno
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("Error: {}".format(err))
|
||||||
|
ret = 1
|
||||||
|
finally:
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
fpid = os.fork()
|
||||||
|
if fpid > 0:
|
||||||
|
sys.exit(0)
|
||||||
|
with open(SERVER_LOG, mode='w', encoding='utf-8') as log:
|
||||||
|
os.dup2(log.fileno(), sys.stdout.fileno())
|
||||||
|
os.dup2(log.fileno(), sys.stderr.fileno())
|
||||||
|
except OSError as ferr:
|
||||||
|
print("Fork #1 failed: {} {}".format(ferr.errno, ferr.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
fpid = os.fork()
|
||||||
|
if fpid > 0:
|
||||||
|
sys.exit(0)
|
||||||
|
except OSError as ferr:
|
||||||
|
print("Fork #2 failed: {} {}".format(ferr.errno, ferr.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Start the daemon main loop
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
149
tests/server_http.pyw
Normal file
149
tests/server_http.pyw
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Windows: Implementation of a HTTP server"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
||||||
|
from make_certificates import CertificateMaker
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
CONF_PATH = os.path.join(RESULT_PATH, "./Testing/conf/")
|
||||||
|
LOGS_PATH = os.path.join(RESULT_PATH, "./Testing/logs/")
|
||||||
|
REQUEST = os.path.join(FILES_PATH, "./jreq.tsq")
|
||||||
|
RESPONS = os.path.join(FILES_PATH, "./jresp.tsr")
|
||||||
|
OPENSSL_CONF = os.path.join(CONF_PATH, "./openssl_tsa.cnf")
|
||||||
|
SERVER_LOG = os.path.join(LOGS_PATH, "./server.log")
|
||||||
|
URL_LOG = os.path.join(LOGS_PATH, "./url.log")
|
||||||
|
|
||||||
|
|
||||||
|
OPENSSL_TS = ["openssl", "ts",
|
||||||
|
"-reply", "-config", OPENSSL_CONF,
|
||||||
|
"-passin", "pass:passme",
|
||||||
|
"-queryfile", REQUEST,
|
||||||
|
"-out", RESPONS]
|
||||||
|
|
||||||
|
|
||||||
|
class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
|
"""Handle the HTTP POST request that arrive at the server"""
|
||||||
|
|
||||||
|
def __init__(self, request, client_address, server):
|
||||||
|
# Save the server handle
|
||||||
|
self.server = server
|
||||||
|
SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
|
||||||
|
|
||||||
|
def do_GET(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the GET request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/pkix-crl")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
# Read the file and send the contents
|
||||||
|
if url.path == "/intermediateCA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./CACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
if url.path == "/TSACA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./TSACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP GET request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
def do_POST(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the POST request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
if url.path == "/kill_server":
|
||||||
|
self.log_message(f"Deleting file: {URL_LOG}")
|
||||||
|
os.remove(f"{URL_LOG}")
|
||||||
|
self.send_header('Content-type', 'text/plain')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(bytes('Shutting down HTTP server', 'utf-8'))
|
||||||
|
self.server.shutdown()
|
||||||
|
else:
|
||||||
|
content_length = int(self.headers['Content-Length'])
|
||||||
|
post_data = self.rfile.read(content_length)
|
||||||
|
with open(REQUEST, mode="wb") as file:
|
||||||
|
file.write(post_data)
|
||||||
|
openssl = subprocess.run(OPENSSL_TS,
|
||||||
|
check=True, universal_newlines=True)
|
||||||
|
openssl.check_returncode()
|
||||||
|
self.send_header("Content-type", "application/timestamp-reply")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
with open(RESPONS, mode="rb") as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP POST request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
class HttpServerThread():
|
||||||
|
"""TSA server thread handler"""
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.server = None
|
||||||
|
self.server_thread = None
|
||||||
|
|
||||||
|
def start_server(self, port) -> (int):
|
||||||
|
"""Starting HTTP server on 127.0.0.1 and a random available port for binding"""
|
||||||
|
self.server = ThreadingHTTPServer(('127.0.0.1', port), RequestHandler)
|
||||||
|
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
||||||
|
self.server_thread.start()
|
||||||
|
hostname, port = self.server.server_address[:2]
|
||||||
|
print("HTTP server started, URL http://{}:{}".format(hostname, port))
|
||||||
|
return port
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Start HTTP server"""
|
||||||
|
|
||||||
|
ret = 0
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="port number"
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
sys.stdout = open(SERVER_LOG, "w")
|
||||||
|
sys.stderr = open(SERVER_LOG, "a")
|
||||||
|
server = HttpServerThread()
|
||||||
|
port = server.start_server(args.port)
|
||||||
|
with open(URL_LOG, mode="w") as file:
|
||||||
|
file.write("127.0.0.1:{}".format(port))
|
||||||
|
tests = CertificateMaker(port, SERVER_LOG)
|
||||||
|
tests.make_certs()
|
||||||
|
except OSError as err:
|
||||||
|
print("OSError: {}".format(err))
|
||||||
|
ret = err.errno
|
||||||
|
finally:
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
57
tests/sources/CatalogDefinitionFileName.cdf
Normal file
57
tests/sources/CatalogDefinitionFileName.cdf
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# https://learn.microsoft.com/en-us/windows/win32/seccrypto/makecat
|
||||||
|
# makecat -v CatalogDefinitionFileName.cdf
|
||||||
|
|
||||||
|
# Define information about the entire catalog file.
|
||||||
|
[CatalogHeader]
|
||||||
|
|
||||||
|
# Name of the catalog file, including its extension.
|
||||||
|
Name=unsigned.cat
|
||||||
|
|
||||||
|
# Directory where the created unsigned.cat file will be placed.
|
||||||
|
ResultDir=..\files
|
||||||
|
|
||||||
|
# This option is not supported. Default value 1 is used.
|
||||||
|
PublicVersion=0x0000001
|
||||||
|
|
||||||
|
# Catalog version.
|
||||||
|
# If the version is set to 2, the HashAlgorithms option must contain SHA256.
|
||||||
|
CatalogVersion=2
|
||||||
|
|
||||||
|
# Name of the hashing algorithm used.
|
||||||
|
HashAlgorithms=SHA256
|
||||||
|
|
||||||
|
# Specifies whether to hash the files listed in the <HASH> option in the [CatalogFiles] section
|
||||||
|
PageHashes=true
|
||||||
|
|
||||||
|
# Type of message encoding used.
|
||||||
|
# The default EncodingType is PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0x00010001
|
||||||
|
EncodingType=0x00010001
|
||||||
|
|
||||||
|
# Specify an attribute of the catalog file.
|
||||||
|
# Set 1.3.6.1.4.1.311.12.2.1 CAT_NAMEVALUE_OBJID
|
||||||
|
# CATATTR1={type}:{oid}:{value} (optional)
|
||||||
|
# The OSAttr attribute specifies the target Windows version
|
||||||
|
CATATTR1=0x11010001:OSAttr:2:6.0
|
||||||
|
|
||||||
|
# Define each member of the catalog file.
|
||||||
|
[CatalogFiles]
|
||||||
|
|
||||||
|
<HASH>PEfile=..\files\unsigned.exe
|
||||||
|
# 0x00010000 Attribute is represented in plaintext. No conversion will be done.
|
||||||
|
<HASH>PEfileATTR1=0x11010001:File:unsigned.exe
|
||||||
|
|
||||||
|
<HASH>MSIfile=..\files\unsigned.msi
|
||||||
|
# 0x00020000 Attribute is represented in base-64 encoding.
|
||||||
|
<HASH>MSIfileATTR1=0x11020001:File:dW5zaWduZWQubXNp
|
||||||
|
|
||||||
|
<HASH>CABfile=..\files\unsigned.ex_
|
||||||
|
<HASH>CABfileATTR1=0x11010001:File:unsigned.ex_
|
||||||
|
|
||||||
|
<HASH>PS1file=..\files\unsigned.ps1
|
||||||
|
<HASH>PS1fileATTR1=0x11010001:File:unsigned.ps1
|
||||||
|
|
||||||
|
<HASH>PSC1file=..\files\unsigned.psc1
|
||||||
|
<HASH>PSC1fileATTR1=0x11010001:File:unsigned.psc1
|
||||||
|
|
||||||
|
<HASH>MOFfile=..\files\unsigned.mof
|
||||||
|
<HASH>MOFfileATTR1=0x11010001:File:unsigned.mof
|
Binary file not shown.
108
tests/start_server.py
Normal file
108
tests/start_server.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Wait for all tests certificate, compute leafhash"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import binascii
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import platform
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
LOGS_PATH = os.path.join(RESULT_PATH, "./Testing/logs/")
|
||||||
|
SERVER_LOG = os.path.join(LOGS_PATH, "./server.log")
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
DEFAULT_PYTHON = "C:/Program Files/Python/Python311/pythonw.exe"
|
||||||
|
DEFAULT_PROG = os.path.join(RESULT_PATH, "./Testing/server_http.pyw")
|
||||||
|
else:
|
||||||
|
DEFAULT_PYTHON = "/usr/bin/python3"
|
||||||
|
DEFAULT_PROG = os.path.join(RESULT_PATH, "./Testing/server_http.py")
|
||||||
|
|
||||||
|
|
||||||
|
def compute_sha256(file_name) -> str:
|
||||||
|
"""Compute a SHA256 hash of the leaf certificate (in DER form)"""
|
||||||
|
|
||||||
|
sha256_hash = hashlib.sha256()
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name)
|
||||||
|
with open(file_path, mode="rb") as file:
|
||||||
|
for bajt in iter(lambda: file.read(4096),b""):
|
||||||
|
sha256_hash.update(bajt)
|
||||||
|
return sha256_hash.hexdigest()
|
||||||
|
|
||||||
|
def clear_catalog(certs_path) -> None:
|
||||||
|
""""Clear a test certificates catalog."""
|
||||||
|
|
||||||
|
if os.path.exists(certs_path):
|
||||||
|
#Remove old test certificates
|
||||||
|
for root, _, files in os.walk(certs_path):
|
||||||
|
for file in files:
|
||||||
|
os.remove(os.path.join(root, file))
|
||||||
|
else:
|
||||||
|
os.mkdir(certs_path)
|
||||||
|
|
||||||
|
# Generate 16 random bytes and convert to hex
|
||||||
|
random_hex = binascii.b2a_hex(os.urandom(16)).decode()
|
||||||
|
serial = os.path.join(certs_path, "./tsa-serial")
|
||||||
|
with open(serial, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write(random_hex)
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Wait for all tests certificate, compute leafhash"""
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--exe",
|
||||||
|
type=pathlib.Path,
|
||||||
|
default=DEFAULT_PYTHON,
|
||||||
|
help=f"the path to the python3 executable to use"
|
||||||
|
f"(default: {DEFAULT_PYTHON})",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--script",
|
||||||
|
type=pathlib.Path,
|
||||||
|
default=DEFAULT_PROG,
|
||||||
|
help=f"the path to the python script to run"
|
||||||
|
f"(default: {DEFAULT_PROG})",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
clear_catalog(CERTS_PATH)
|
||||||
|
#pylint: disable=consider-using-with
|
||||||
|
subprocess.Popen([str(args.exe), str(args.script)])
|
||||||
|
|
||||||
|
cert_log = os.path.join(CERTS_PATH, "./cert.log")
|
||||||
|
while not (os.path.exists(cert_log) and os.path.getsize(cert_log) > 0):
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
leafhash = compute_sha256("cert.der")
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./leafhash.txt")
|
||||||
|
with open(file_path, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("SHA256:{}".format(leafhash))
|
||||||
|
|
||||||
|
except OSError as err:
|
||||||
|
with open(SERVER_LOG, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("OSError: {}".format(err))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
with open(SERVER_LOG, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("Error: {}".format(err))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
@ -1,151 +0,0 @@
|
|||||||
"""Implementation of a Time Stamping Authority HTTP server"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import contextlib
|
|
||||||
import os
|
|
||||||
import pathlib
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import threading
|
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
||||||
|
|
||||||
RESULT_PATH = os.getcwd()
|
|
||||||
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
|
||||||
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
|
||||||
CONF_PATH = os.path.join(RESULT_PATH, "./Testing/conf/")
|
|
||||||
DEFAULT_IN = os.path.join(FILES_PATH, "./unsigned.exe")
|
|
||||||
DEFAULT_OUT = os.path.join(FILES_PATH, "./ts.exe")
|
|
||||||
DEFAULT_CERT = os.path.join(CERTS_PATH, "./cert.pem")
|
|
||||||
DEFAULT_KEY = os.path.join(CERTS_PATH, "./key.pem")
|
|
||||||
DEFAULT_CROSSCERT = os.path.join(CERTS_PATH, "./crosscert.pem")
|
|
||||||
OPENSSL_CONF = os.path.join(CONF_PATH, "./openssl_tsa.cnf")
|
|
||||||
REQUEST = os.path.join(FILES_PATH, "./jreq.tsq")
|
|
||||||
RESPONS = os.path.join(FILES_PATH, "./jresp.tsr")
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(RESULT_PATH, "./Release/")):
|
|
||||||
OSSLSIGNCODE_FILE = os.path.join(RESULT_PATH, "./Release/osslsigncode")
|
|
||||||
elif os.path.exists(os.path.join(RESULT_PATH, "./Debug/")):
|
|
||||||
OSSLSIGNCODE_FILE = os.path.join(RESULT_PATH, "./Debug/osslsigncode")
|
|
||||||
else:
|
|
||||||
OSSLSIGNCODE_FILE = os.path.join(RESULT_PATH, "./osslsigncode")
|
|
||||||
|
|
||||||
DEFAULT_OPENSSL = ["openssl", "ts",
|
|
||||||
"-reply", "-config", OPENSSL_CONF,
|
|
||||||
"-passin", "pass:passme",
|
|
||||||
"-queryfile", REQUEST,
|
|
||||||
"-out", RESPONS]
|
|
||||||
|
|
||||||
|
|
||||||
class RequestHandler(BaseHTTPRequestHandler):
|
|
||||||
"""Handle the HTTP POST request that arrive at the server"""
|
|
||||||
|
|
||||||
def do_POST(self):
|
|
||||||
""""Serves the POST request type"""
|
|
||||||
try:
|
|
||||||
content_length = int(self.headers['Content-Length'])
|
|
||||||
post_data = self.rfile.read(content_length)
|
|
||||||
with open(REQUEST, mode="wb") as file:
|
|
||||||
file.write(post_data)
|
|
||||||
openssl = subprocess.run(DEFAULT_OPENSSL, check=True, text=True)
|
|
||||||
openssl.check_returncode()
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "application/timestamp-reply")
|
|
||||||
self.end_headers()
|
|
||||||
resp_data = None
|
|
||||||
with open(RESPONS, mode="rb") as file:
|
|
||||||
resp_data = file.read()
|
|
||||||
self.wfile.write(resp_data)
|
|
||||||
except Exception as err: # pylint: disable=broad-except
|
|
||||||
print(f"HTTP POST request error: {err}")
|
|
||||||
|
|
||||||
|
|
||||||
class HttpServerThread():
|
|
||||||
"""TSA server thread handler"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.server = None
|
|
||||||
self.server_thread = None
|
|
||||||
|
|
||||||
def start_server(self) -> (str, int):
|
|
||||||
"""Starting TSA server on localhost and a first available port"""
|
|
||||||
self.server = HTTPServer(("127.0.0.1", 0), RequestHandler)
|
|
||||||
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
|
||||||
self.server_thread.start()
|
|
||||||
hostname, port = self.server.server_address[:2]
|
|
||||||
print(f"Timestamp server started, URL: http://{hostname}:{port}")
|
|
||||||
return hostname, port
|
|
||||||
|
|
||||||
def shut_down(self):
|
|
||||||
"""Shutting down the server"""
|
|
||||||
if self.server:
|
|
||||||
self.server.shutdown()
|
|
||||||
self.server_thread.join()
|
|
||||||
print("Server is down")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args() -> str:
|
|
||||||
"""Parse the command-line arguments."""
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"--input",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_IN,
|
|
||||||
help="input file"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--output",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_OUT,
|
|
||||||
help="output file"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--certs",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_CERT,
|
|
||||||
help="signing certificate"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--key",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_KEY,
|
|
||||||
help="private key"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--crosscert",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_CROSSCERT,
|
|
||||||
help="additional certificates"
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
program = [OSSLSIGNCODE_FILE, "sign", "-in", args.input, "-out", args.output,
|
|
||||||
"-certs", args.certs, "-key", args.key,
|
|
||||||
"-addUnauthenticatedBlob", "-add-msi-dse", "-comm", "-ph", "-jp", "low",
|
|
||||||
"-h", "sha384", "-time", "1556668800", "-i", "https://www.osslsigncode.com/",
|
|
||||||
"-n", "osslsigncode", "-ac", args.crosscert, "-ts"]
|
|
||||||
return program
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
"""Main program"""
|
|
||||||
ret = 0
|
|
||||||
program = parse_args()
|
|
||||||
server = HttpServerThread()
|
|
||||||
hostname, port = server.start_server()
|
|
||||||
program.append(f"{hostname}:{port}")
|
|
||||||
try:
|
|
||||||
osslsigncode = subprocess.run(program, check=True, text=True)
|
|
||||||
osslsigncode.check_returncode()
|
|
||||||
except subprocess.CalledProcessError as err:
|
|
||||||
ret = err.returncode
|
|
||||||
except OSError as err:
|
|
||||||
print(f"OSError: {err}")
|
|
||||||
ret = err.errno
|
|
||||||
except Exception as err: # pylint: disable=broad-except
|
|
||||||
print(f"osslsigncode error: {err}")
|
|
||||||
ret = 1
|
|
||||||
finally:
|
|
||||||
server.shut_down()
|
|
||||||
sys.exit(ret)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
347
utf.c
Normal file
347
utf.c
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/
|
||||||
|
// 10 november 2016
|
||||||
|
#include "utf.h"
|
||||||
|
|
||||||
|
// this code imitates Go's unicode/utf8 and unicode/utf16
|
||||||
|
// the biggest difference is that a rune is unsigned instead of signed (because Go guarantees what a right shift on a signed number will do, whereas C does not)
|
||||||
|
// it is also an imitation so we can license it under looser terms than the Go source
|
||||||
|
#define badrune 0xFFFD
|
||||||
|
|
||||||
|
// encoded must be at most 4 bytes
|
||||||
|
// TODO clean this code up somehow
|
||||||
|
size_t utf8EncodeRune(uint32_t rune, char *encoded)
|
||||||
|
{
|
||||||
|
uint8_t b, c, d, e;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
// not in the valid range for Unicode
|
||||||
|
if (rune > 0x10FFFF)
|
||||||
|
rune = badrune;
|
||||||
|
// surrogate runes cannot be encoded
|
||||||
|
if (rune >= 0xD800 && rune < 0xE000)
|
||||||
|
rune = badrune;
|
||||||
|
|
||||||
|
if (rune < 0x80) { // ASCII bytes represent themselves
|
||||||
|
b = (uint8_t) (rune & 0xFF);
|
||||||
|
n = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (rune < 0x800) { // two-byte encoding
|
||||||
|
c = (uint8_t) (rune & 0x3F);
|
||||||
|
c |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
b = (uint8_t) (rune & 0x1F);
|
||||||
|
b |= 0xC0;
|
||||||
|
n = 2;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (rune < 0x10000) { // three-byte encoding
|
||||||
|
d = (uint8_t) (rune & 0x3F);
|
||||||
|
d |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
c = (uint8_t) (rune & 0x3F);
|
||||||
|
c |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
b = (uint8_t) (rune & 0x0F);
|
||||||
|
b |= 0xE0;
|
||||||
|
n = 3;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
// otherwise use a four-byte encoding
|
||||||
|
e = (uint8_t) (rune & 0x3F);
|
||||||
|
e |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
d = (uint8_t) (rune & 0x3F);
|
||||||
|
d |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
c = (uint8_t) (rune & 0x3F);
|
||||||
|
c |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
b = (uint8_t) (rune & 0x07);
|
||||||
|
b |= 0xF0;
|
||||||
|
n = 4;
|
||||||
|
|
||||||
|
done:
|
||||||
|
encoded[0] = (char)b;
|
||||||
|
if (n > 1)
|
||||||
|
encoded[1] = (char)c;
|
||||||
|
if (n > 2)
|
||||||
|
encoded[2] = (char)d;
|
||||||
|
if (n > 3)
|
||||||
|
encoded[3] = (char)e;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune)
|
||||||
|
{
|
||||||
|
uint8_t b, c;
|
||||||
|
uint8_t lowestAllowed, highestAllowed;
|
||||||
|
size_t i, expected;
|
||||||
|
int bad;
|
||||||
|
|
||||||
|
b = (uint8_t) (*s);
|
||||||
|
if (b < 0x80) { // ASCII bytes represent themselves
|
||||||
|
*rune = b;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
// 0xC0 and 0xC1 cover 2-byte overlong equivalents
|
||||||
|
// 0xF5 to 0xFD cover values > 0x10FFFF
|
||||||
|
// 0xFE and 0xFF were never defined (always illegal)
|
||||||
|
if (b < 0xC2 || b > 0xF4) { // invalid
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this determines the range of allowed first continuation bytes
|
||||||
|
lowestAllowed = 0x80;
|
||||||
|
highestAllowed = 0xBF;
|
||||||
|
switch (b) {
|
||||||
|
case 0xE0:
|
||||||
|
// disallow 3-byte overlong equivalents
|
||||||
|
lowestAllowed = 0xA0;
|
||||||
|
break;
|
||||||
|
case 0xED:
|
||||||
|
// disallow surrogate characters
|
||||||
|
highestAllowed = 0x9F;
|
||||||
|
break;
|
||||||
|
case 0xF0:
|
||||||
|
// disallow 4-byte overlong equivalents
|
||||||
|
lowestAllowed = 0x90;
|
||||||
|
break;
|
||||||
|
case 0xF4:
|
||||||
|
// disallow values > 0x10FFFF
|
||||||
|
highestAllowed = 0x8F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and this determines how many continuation bytes are expected
|
||||||
|
expected = 1;
|
||||||
|
if (b >= 0xE0)
|
||||||
|
expected++;
|
||||||
|
if (b >= 0xF0)
|
||||||
|
expected++;
|
||||||
|
if (nElem != 0) { // are there enough bytes?
|
||||||
|
nElem--;
|
||||||
|
if (nElem < expected) { // nope
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that everything is correct
|
||||||
|
// if not, **only** consume the initial byte
|
||||||
|
bad = 0;
|
||||||
|
for (i = 0; i < expected; i++) {
|
||||||
|
c = (uint8_t) (s[1 + i]);
|
||||||
|
if (c < lowestAllowed || c > highestAllowed) {
|
||||||
|
bad = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// the old lowestAllowed and highestAllowed is only for the first continuation byte
|
||||||
|
lowestAllowed = 0x80;
|
||||||
|
highestAllowed = 0xBF;
|
||||||
|
}
|
||||||
|
if (bad) {
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do the topmost bits
|
||||||
|
if (b < 0xE0)
|
||||||
|
*rune = b & 0x1F;
|
||||||
|
else if (b < 0xF0)
|
||||||
|
*rune = b & 0x0F;
|
||||||
|
else
|
||||||
|
*rune = b & 0x07;
|
||||||
|
s++; // we can finally move on
|
||||||
|
|
||||||
|
// now do the continuation bytes
|
||||||
|
for (; expected; expected--) {
|
||||||
|
c = (uint8_t) (*s);
|
||||||
|
s++;
|
||||||
|
c &= 0x3F; // strip continuation bits
|
||||||
|
*rune <<= 6;
|
||||||
|
*rune |= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// encoded must have at most 2 elements
|
||||||
|
size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded)
|
||||||
|
{
|
||||||
|
uint16_t low, high;
|
||||||
|
|
||||||
|
// not in the valid range for Unicode
|
||||||
|
if (rune > 0x10FFFF)
|
||||||
|
rune = badrune;
|
||||||
|
// surrogate runes cannot be encoded
|
||||||
|
if (rune >= 0xD800 && rune < 0xE000)
|
||||||
|
rune = badrune;
|
||||||
|
|
||||||
|
if (rune < 0x10000) {
|
||||||
|
encoded[0] = (uint16_t) rune;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rune -= 0x10000;
|
||||||
|
low = (uint16_t) (rune & 0x3FF);
|
||||||
|
rune >>= 10;
|
||||||
|
high = (uint16_t) (rune & 0x3FF);
|
||||||
|
encoded[0] = high | 0xD800;
|
||||||
|
encoded[1] = low | 0xDC00;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO see if this can be cleaned up somehow
|
||||||
|
const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune)
|
||||||
|
{
|
||||||
|
uint16_t high, low;
|
||||||
|
|
||||||
|
if (*s < 0xD800 || *s >= 0xE000) {
|
||||||
|
// self-representing character
|
||||||
|
*rune = *s;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if (*s >= 0xDC00) {
|
||||||
|
// out-of-order surrogates
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if (nElem == 1) { // not enough elements
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
high = *s;
|
||||||
|
high &= 0x3FF;
|
||||||
|
if (s[1] < 0xDC00 || s[1] >= 0xE000) {
|
||||||
|
// bad surrogate pair
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
low = *s;
|
||||||
|
s++;
|
||||||
|
low &= 0x3FF;
|
||||||
|
*rune = high;
|
||||||
|
*rune <<= 10;
|
||||||
|
*rune |= low;
|
||||||
|
*rune += 0x10000;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO find a way to reduce the code in all of these somehow
|
||||||
|
// TODO find a way to remove u as well
|
||||||
|
size_t utf8RuneCount(const char *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const char *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf8DecodeRune(t, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf8DecodeRune(s, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf8UTF16Count(const char *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
uint16_t encoded[2];
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const char *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf8DecodeRune(t, nElem, &rune);
|
||||||
|
len += utf16EncodeRune(rune, encoded);
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf8DecodeRune(s, nElem, &rune);
|
||||||
|
len += utf16EncodeRune(rune, encoded);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf16RuneCount(const uint16_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const uint16_t *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf16DecodeRune(t, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf16DecodeRune(s, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf16UTF8Count(const uint16_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
char encoded[4];
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const uint16_t *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf16DecodeRune(t, nElem, &rune);
|
||||||
|
len += utf8EncodeRune(rune, encoded);
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf16DecodeRune(s, nElem, &rune);
|
||||||
|
len += utf8EncodeRune(rune, encoded);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
61
utf.h
Normal file
61
utf.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/
|
||||||
|
// 10 november 2016
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// if nElem == 0, assume the buffer has no upper limit and is '\0' terminated
|
||||||
|
// otherwise, assume buffer is NOT '\0' terminated but is bounded by nElem *elements*
|
||||||
|
|
||||||
|
extern size_t utf8EncodeRune(uint32_t rune, char *encoded);
|
||||||
|
extern const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune);
|
||||||
|
extern size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded);
|
||||||
|
extern const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune);
|
||||||
|
|
||||||
|
extern size_t utf8RuneCount(const char *s, size_t nElem);
|
||||||
|
extern size_t utf8UTF16Count(const char *s, size_t nElem);
|
||||||
|
extern size_t utf16RuneCount(const uint16_t *s, size_t nElem);
|
||||||
|
extern size_t utf16UTF8Count(const uint16_t *s, size_t nElem);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide overloads on Windows for using these functions with wchar_t and WCHAR when wchar_t is a keyword in C++ mode (the default).
|
||||||
|
// Otherwise, you'd need to cast to pass a wchar_t pointer, WCHAR pointer, or equivalent to these functions.
|
||||||
|
// We use __wchar_t to be independent of the setting; see https://blogs.msdn.microsoft.com/oldnewthing/20161201-00/?p=94836 (ironically posted one day after I initially wrote this code!).
|
||||||
|
// TODO check this on MinGW-w64
|
||||||
|
// TODO check this under /Wall
|
||||||
|
// TODO C-style casts enough? or will that fail in /Wall?
|
||||||
|
// TODO same for UniChar/unichar on Mac? if both are unsigned then we have nothing to worry about
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
|
inline size_t utf16EncodeRune(uint32_t rune, __wchar_t *encoded)
|
||||||
|
{
|
||||||
|
return utf16EncodeRune(rune, reinterpret_cast<uint16_t *>(encoded));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const __wchar_t *utf16DecodeRune(const __wchar_t *s, size_t nElem, uint32_t *rune)
|
||||||
|
{
|
||||||
|
const uint16_t *ret;
|
||||||
|
|
||||||
|
ret = utf16DecodeRune(reinterpret_cast<const uint16_t *>(s), nElem, rune);
|
||||||
|
return reinterpret_cast<const __wchar_t *>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t utf16RuneCount(const __wchar_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
return utf16RuneCount(reinterpret_cast<const uint16_t *>(s), nElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t utf16UTF8Count(const __wchar_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
return utf16UTF8Count(reinterpret_cast<const uint16_t *>(s), nElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -3,10 +3,7 @@
|
|||||||
"version-string": "2.4",
|
"version-string": "2.4",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"openssl",
|
"openssl",
|
||||||
"curl",
|
"zlib"
|
||||||
{
|
],
|
||||||
"name": "python3",
|
"builtin-baseline": "9edb1b8e590cc086563301d735cae4b6e732d2d2"
|
||||||
"platform": "!(windows & static) & !osx"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user