mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-07-03 19:52:47 -05:00
Compare commits
66 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@ -7,7 +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.7
|
version: osslsigncode-2.8
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -90,12 +90,28 @@ jobs:
|
|||||||
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: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libssl-dev libcurl4-openssl-dev faketime
|
sudo apt-get install -y libssl-dev libcurl4-openssl-dev faketime
|
||||||
|
|
||||||
|
- name: Install brew dependencies (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
run: |
|
||||||
|
brew install python@3.8
|
||||||
|
|
||||||
- name: Install Xcode (macOS)
|
- name: Install Xcode (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
uses: maxim-lobanov/setup-xcode@v1
|
uses: maxim-lobanov/setup-xcode@v1
|
||||||
@ -129,8 +145,8 @@ jobs:
|
|||||||
working-directory: ${{github.workspace}}/build
|
working-directory: ${{github.workspace}}/build
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
python3 --version
|
python3.8 --version
|
||||||
python3 ./Testing/server_http.py --port 19254
|
python3.8 ./Testing/server_http.py --port 19254
|
||||||
while test ! -s ./Testing/logs/port.log; do sleep 1; done
|
while test ! -s ./Testing/logs/port.log; do sleep 1; done
|
||||||
|
|
||||||
- name: Start HTTP server (Windows)
|
- name: Start HTTP server (Windows)
|
||||||
|
@ -10,7 +10,7 @@ set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
|||||||
|
|
||||||
# configure basic project information
|
# configure basic project information
|
||||||
project(osslsigncode
|
project(osslsigncode
|
||||||
VERSION 2.7
|
VERSION 2.8
|
||||||
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)
|
||||||
@ -48,7 +48,7 @@ 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 helpers.c msi.c pe.c cab.c cat.c appx.c)
|
target_sources(osslsigncode PRIVATE osslsigncode.c helpers.c utf.c msi.c pe.c cab.c cat.c appx.c script.c)
|
||||||
if(NOT UNIX)
|
if(NOT UNIX)
|
||||||
target_sources(osslsigncode PRIVATE applink.c)
|
target_sources(osslsigncode PRIVATE applink.c)
|
||||||
endif(NOT UNIX)
|
endif(NOT UNIX)
|
||||||
|
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 curl-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 libcurl
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /workdir
|
||||||
|
|
||||||
|
# Declare volume to mount files
|
||||||
|
VOLUME [ "/workdir" ]
|
@ -12,7 +12,7 @@
|
|||||||
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 \
|
x86_64-w64-mingw32-gcc *.c -o osslsigncode.exe \
|
||||||
-lcrypto -lssl -lcurl \
|
-lcrypto -lssl -lcurl \
|
||||||
-D 'PACKAGE_STRING="osslsigncode x.y"' \
|
-D 'PACKAGE_STRING="osslsigncode x.y"' \
|
||||||
-D 'PACKAGE_BUGREPORT="Your.Email@example.com"' \
|
-D 'PACKAGE_BUGREPORT="Your.Email@example.com"' \
|
||||||
@ -71,7 +71,7 @@
|
|||||||
3) Build 64-bit Windows executables.
|
3) Build 64-bit Windows executables.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
cd osslsigncode-folder
|
||||||
x86_64-w64-mingw32-gcc osslsigncode.c msi.c -o osslsigncode.exe \
|
x86_64-w64-mingw32-gcc *.c -o osslsigncode.exe \
|
||||||
-L 'C:/OpenSSL/lib/' -lcrypto -lssl \
|
-L 'C:/OpenSSL/lib/' -lcrypto -lssl \
|
||||||
-I 'C:/OpenSSL/include/' \
|
-I 'C:/OpenSSL/include/' \
|
||||||
-L 'C:/curl/lib' -lcurl \
|
-L 'C:/curl/lib' -lcurl \
|
||||||
|
22
NEWS.md
22
NEWS.md
@ -1,5 +1,27 @@
|
|||||||
# osslsigncode change log
|
# osslsigncode change log
|
||||||
|
|
||||||
|
### 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)
|
### 2.7 (2023.09.19)
|
||||||
|
|
||||||
- fixed signing CAB files (by Michael Brown)
|
- fixed signing CAB files (by Michael Brown)
|
||||||
|
@ -39,7 +39,7 @@ 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:
|
||||||
```
|
```
|
||||||
|
264
appx.c
264
appx.c
@ -6,6 +6,7 @@
|
|||||||
* Copyright (C) 2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
* Copyright (C) 2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
*
|
*
|
||||||
|
* APPX files do not support nesting (multiple signature)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
@ -16,10 +17,22 @@
|
|||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#ifndef PRIX64
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define PRIX64 "I64X"
|
||||||
|
#else /* _MSC_VER */
|
||||||
|
#if ULONG_MAX == 0xFFFFFFFFFFFFFFFF
|
||||||
|
#define PRIX64 "lX"
|
||||||
|
#else /* ULONG_MAX == 0xFFFFFFFFFFFFFFFF */
|
||||||
|
#define PRIX64 "llX"
|
||||||
|
#endif /* ULONG_MAX == 0xFFFFFFFFFFFFFFFF */
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
#endif /* PRIX64 */
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define fseeko _fseeki64
|
#define fseeko _fseeki64
|
||||||
#define ftello _ftelli64
|
#define ftello _ftelli64
|
||||||
#endif
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#define EOCDR_SIZE 22
|
#define EOCDR_SIZE 22
|
||||||
#define ZIP64_EOCD_LOCATOR_SIZE 20
|
#define ZIP64_EOCD_LOCATOR_SIZE 20
|
||||||
@ -233,26 +246,30 @@ struct appx_ctx_st {
|
|||||||
|
|
||||||
/* FILE_FORMAT method prototypes */
|
/* FILE_FORMAT method prototypes */
|
||||||
static FILE_FORMAT_CTX *appx_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
static FILE_FORMAT_CTX *appx_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
|
static const EVP_MD *appx_md_get(FILE_FORMAT_CTX *ctx);
|
||||||
static ASN1_OBJECT *appx_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
static ASN1_OBJECT *appx_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *appx_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
static int appx_hash_length_get(FILE_FORMAT_CTX *ctx);
|
static int appx_hash_length_get(FILE_FORMAT_CTX *ctx);
|
||||||
static int appx_check_file(FILE_FORMAT_CTX *ctx, int detached);
|
|
||||||
static int appx_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
static int appx_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
static PKCS7 *appx_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
static PKCS7 *appx_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
static PKCS7 *appx_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int appx_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static PKCS7 *appx_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
static int appx_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
static int appx_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static BIO *appx_bio_free(BIO *hash, BIO *outdata);
|
static void appx_bio_free(BIO *hash, BIO *outdata);
|
||||||
static void appx_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static void appx_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
FILE_FORMAT file_format_appx = {
|
FILE_FORMAT file_format_appx = {
|
||||||
.ctx_new = appx_ctx_new,
|
.ctx_new = appx_ctx_new,
|
||||||
|
.md_get = appx_md_get,
|
||||||
.data_blob_get = appx_spc_sip_info_get,
|
.data_blob_get = appx_spc_sip_info_get,
|
||||||
|
.pkcs7_contents_get = appx_pkcs7_contents_get,
|
||||||
.hash_length_get = appx_hash_length_get,
|
.hash_length_get = appx_hash_length_get,
|
||||||
.check_file = appx_check_file,
|
|
||||||
.verify_digests = appx_verify_digests,
|
.verify_digests = appx_verify_digests,
|
||||||
.pkcs7_extract = appx_pkcs7_extract,
|
.pkcs7_extract = appx_pkcs7_extract,
|
||||||
.remove_pkcs7 = appx_remove_pkcs7,
|
.remove_pkcs7 = appx_remove_pkcs7,
|
||||||
.pkcs7_prepare = appx_pkcs7_prepare,
|
.process_data = appx_process_data,
|
||||||
|
.pkcs7_signature_new = appx_pkcs7_signature_new,
|
||||||
.append_pkcs7 = appx_append_pkcs7,
|
.append_pkcs7 = appx_append_pkcs7,
|
||||||
.bio_free = appx_bio_free,
|
.bio_free = appx_bio_free,
|
||||||
.ctx_cleanup = appx_ctx_cleanup,
|
.ctx_cleanup = appx_ctx_cleanup,
|
||||||
@ -277,8 +294,8 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
|
|||||||
static void zipWriteLocalHeader(BIO *bio, uint64_t *sizeonDisk, ZIP_LOCAL_HEADER *heade);
|
static void zipWriteLocalHeader(BIO *bio, uint64_t *sizeonDisk, ZIP_LOCAL_HEADER *heade);
|
||||||
static int zipEntryExist(ZIP_FILE *zip, const char *name);
|
static int zipEntryExist(ZIP_FILE *zip, const char *name);
|
||||||
static u_char *zipCalcDigest(ZIP_FILE *zip, const char *fileName, const EVP_MD *md);
|
static u_char *zipCalcDigest(ZIP_FILE *zip, const char *fileName, const EVP_MD *md);
|
||||||
static int zipReadFileDataByName(uint8_t **pData, uint64_t *dataSize, ZIP_FILE *zip, const char *name);
|
static size_t zipReadFileDataByName(uint8_t **pData, ZIP_FILE *zip, const char *name);
|
||||||
static int zipReadFileData(ZIP_FILE *zip, uint8_t **pData, uint64_t *dataSize, ZIP_CENTRAL_DIRECTORY_ENTRY *entry);
|
static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECTORY_ENTRY *entry);
|
||||||
static int zipReadLocalHeader(ZIP_LOCAL_HEADER *header, ZIP_FILE *zip, uint64_t compressedSize);
|
static int zipReadLocalHeader(ZIP_LOCAL_HEADER *header, ZIP_FILE *zip, uint64_t compressedSize);
|
||||||
static int zipInflate(uint8_t *dest, uint64_t *destLen, uint8_t *source, uLong *sourceLen);
|
static int zipInflate(uint8_t *dest, uint64_t *destLen, uint8_t *source, uLong *sourceLen);
|
||||||
static int zipDeflate(uint8_t *dest, uint64_t *destLen, uint8_t *source, uLong sourceLen);
|
static int zipDeflate(uint8_t *dest, uint64_t *destLen, uint8_t *source, uLong sourceLen);
|
||||||
@ -344,10 +361,8 @@ static FILE_FORMAT_CTX *appx_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *ou
|
|||||||
if (zipGetCDEntryByName(zip, APPXBUNDLE_MANIFEST_FILENAME)) {
|
if (zipGetCDEntryByName(zip, APPXBUNDLE_MANIFEST_FILENAME)) {
|
||||||
ctx->appx_ctx->isBundle = 1;
|
ctx->appx_ctx->isBundle = 1;
|
||||||
}
|
}
|
||||||
if (options->nest)
|
if (options->cmd == CMD_SIGN || options->cmd==CMD_ATTACH
|
||||||
/* I've not tried using set_nested_signature as signtool won't do this */
|
|| options->cmd==CMD_ADD || options->cmd == CMD_EXTRACT_DATA) {
|
||||||
printf("Warning: APPX files do not support nesting (multiple signature)\n");
|
|
||||||
if (options->cmd == CMD_SIGN || options->cmd==CMD_ATTACH || options->cmd==CMD_ADD) {
|
|
||||||
printf("Warning: Ignore -h option, use the hash algorithm specified in AppxBlockMap.xml\n");
|
printf("Warning: Ignore -h option, use the hash algorithm specified in AppxBlockMap.xml\n");
|
||||||
}
|
}
|
||||||
if (options->pagehash == 1)
|
if (options->pagehash == 1)
|
||||||
@ -359,6 +374,16 @@ static FILE_FORMAT_CTX *appx_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *ou
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a hash algorithm specified in the AppxBlockMap.xml file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] hash algorithm
|
||||||
|
*/
|
||||||
|
static const EVP_MD *appx_md_get(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return ctx->appx_ctx->md;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate and return SpcSipInfo object.
|
* Allocate and return SpcSipInfo object.
|
||||||
* [out] p: SpcSipInfo data
|
* [out] p: SpcSipInfo data
|
||||||
@ -394,6 +419,41 @@ static ASN1_OBJECT *appx_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX
|
|||||||
return dtype; /* OK */
|
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 *appx_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
ZIP_CENTRAL_DIRECTORY_ENTRY *entry;
|
||||||
|
BIO *bhash;
|
||||||
|
|
||||||
|
/* squash unused parameter warnings */
|
||||||
|
(void)md;
|
||||||
|
(void)hash;
|
||||||
|
|
||||||
|
/* Create and append a new signature content types entry */
|
||||||
|
entry = zipGetCDEntryByName(ctx->appx_ctx->zip, CONTENT_TYPES_FILENAME);
|
||||||
|
if (!entry) {
|
||||||
|
printf("Not a valid .appx file: content types file missing\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!appx_append_ct_signature_entry(ctx->appx_ctx->zip, entry)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
bhash = appx_calculate_hashes(ctx);
|
||||||
|
if (!bhash) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(bhash, ctx);
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return pkcs7_set_content(content);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get concatenated hashes length.
|
* Get concatenated hashes length.
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
@ -404,25 +464,6 @@ static int appx_hash_length_get(FILE_FORMAT_CTX *ctx)
|
|||||||
return ctx->appx_ctx->hashlen;
|
return ctx->appx_ctx->hashlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the signature exists.
|
|
||||||
* [in] ctx: structure holds input and output data
|
|
||||||
* [in] detached: embedded/detached PKCS#7 signature switch
|
|
||||||
* [returns] 0 on error or 1 on success
|
|
||||||
*/
|
|
||||||
static int appx_check_file(FILE_FORMAT_CTX *ctx, int detached)
|
|
||||||
{
|
|
||||||
if (detached) {
|
|
||||||
printf("APPX format does not support detached PKCS#7 signature\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
if (!zipEntryExist(ctx->appx_ctx->zip, APP_SIGNATURE_FILENAME)) {
|
|
||||||
printf("%s does not exist\n", APP_SIGNATURE_FILENAME);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate message digest and compare to value retrieved from PKCS#7 signedData.
|
* Calculate message digest and compare to value retrieved from PKCS#7 signedData.
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
@ -470,9 +511,15 @@ static PKCS7 *appx_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
|||||||
PKCS7 *p7;
|
PKCS7 *p7;
|
||||||
uint8_t *data = NULL;
|
uint8_t *data = NULL;
|
||||||
const u_char *blob;
|
const u_char *blob;
|
||||||
uint64_t dataSize = 0;
|
size_t dataSize;
|
||||||
|
|
||||||
if (!zipReadFileDataByName(&data, &dataSize, ctx->appx_ctx->zip, APP_SIGNATURE_FILENAME)) {
|
/* Check if the signature exists */
|
||||||
|
if (!zipEntryExist(ctx->appx_ctx->zip, APP_SIGNATURE_FILENAME)) {
|
||||||
|
printf("%s does not exist\n", APP_SIGNATURE_FILENAME);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
dataSize = zipReadFileDataByName(&data, ctx->appx_ctx->zip, APP_SIGNATURE_FILENAME);
|
||||||
|
if (dataSize <= 0) {
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
/* P7X format is just 0x504B4358 (PKCX) followed by PKCS#7 data in the DER format */
|
/* P7X format is just 0x504B4358 (PKCX) followed by PKCS#7 data in the DER format */
|
||||||
@ -496,6 +543,8 @@ static PKCS7 *appx_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
|||||||
*/
|
*/
|
||||||
static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
size_t dataSize;
|
||||||
uint64_t cdOffset, noEntries = 0;
|
uint64_t cdOffset, noEntries = 0;
|
||||||
ZIP_FILE *zip = ctx->appx_ctx->zip;
|
ZIP_FILE *zip = ctx->appx_ctx->zip;
|
||||||
ZIP_CENTRAL_DIRECTORY_ENTRY *entry = zipGetCDEntryByName(zip, CONTENT_TYPES_FILENAME);
|
ZIP_CENTRAL_DIRECTORY_ENTRY *entry = zipGetCDEntryByName(zip, CONTENT_TYPES_FILENAME);
|
||||||
@ -507,6 +556,12 @@ static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
printf("Not a valid .appx file: content types file missing\n");
|
printf("Not a valid .appx file: content types file missing\n");
|
||||||
return 1; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
|
/* read signature data */
|
||||||
|
dataSize = zipReadFileDataByName(&data, ctx->appx_ctx->zip, APP_SIGNATURE_FILENAME);
|
||||||
|
if (dataSize <= 0) {
|
||||||
|
return 1; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
OPENSSL_free(data);
|
||||||
if (!appx_remove_ct_signature_entry(zip, entry)) {
|
if (!appx_remove_ct_signature_entry(zip, entry)) {
|
||||||
printf("Failed to remove signature entry\n");
|
printf("Failed to remove signature entry\n");
|
||||||
return 1; /* FAILED */
|
return 1; /* FAILED */
|
||||||
@ -540,60 +595,78 @@ static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain an existing signature or create a new one.
|
* Modify specific type data.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO (unused)
|
* [out] hash: message digest BIO (unused)
|
||||||
* [out] outdata: outdata file BIO (unused)
|
* [out] outdata: outdata file BIO (unused)
|
||||||
* [returns] pointer to PKCS#7 structure
|
* [returns] 1 on error or 0 on success
|
||||||
*/
|
*/
|
||||||
static PKCS7 *appx_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int appx_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
PKCS7 *cursig = NULL, *p7 = NULL;
|
ZIP_CENTRAL_DIRECTORY_ENTRY *entry;
|
||||||
|
|
||||||
/* squash unused parameter warnings */
|
/* squash unused parameter warnings */
|
||||||
(void)outdata;
|
(void)outdata;
|
||||||
(void)hash;
|
(void)hash;
|
||||||
|
|
||||||
if (ctx->options->cmd == CMD_ADD || ctx->options->cmd == CMD_ATTACH) {
|
/* Create and append a new signature content types entry */
|
||||||
/* Obtain an existing signature */
|
|
||||||
cursig = appx_pkcs7_extract(ctx);
|
|
||||||
if (!cursig) {
|
|
||||||
printf("Unable to extract existing signature\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
return cursig;
|
|
||||||
} else if (ctx->options->cmd == CMD_SIGN) {
|
|
||||||
BIO *hashes;
|
|
||||||
ZIP_CENTRAL_DIRECTORY_ENTRY *entry;
|
|
||||||
|
|
||||||
/* Create a new signature */
|
|
||||||
entry = zipGetCDEntryByName(ctx->appx_ctx->zip, CONTENT_TYPES_FILENAME);
|
entry = zipGetCDEntryByName(ctx->appx_ctx->zip, CONTENT_TYPES_FILENAME);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
printf("Not a valid .appx file: content types file missing\n");
|
printf("Not a valid .appx file: content types file missing\n");
|
||||||
return NULL; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!appx_append_ct_signature_entry(ctx->appx_ctx->zip, entry)) {
|
if (!appx_append_ct_signature_entry(ctx->appx_ctx->zip, entry)) {
|
||||||
return NULL; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
/* create hash blob from concatenated APPX hashes */
|
return 0; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 *appx_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
PKCS7 *p7 = NULL;
|
||||||
|
BIO *hashes;
|
||||||
|
|
||||||
|
/* squash unused parameter warnings */
|
||||||
|
(void)hash;
|
||||||
|
|
||||||
|
/* Create hash blob from concatenated APPX hashes */
|
||||||
hashes = appx_calculate_hashes(ctx);
|
hashes = appx_calculate_hashes(ctx);
|
||||||
if (!hashes) {
|
if (!hashes) {
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
/* Create a new PKCS#7 signature */
|
|
||||||
p7 = pkcs7_create(ctx);
|
p7 = pkcs7_create(ctx);
|
||||||
if (!p7) {
|
if (!p7) {
|
||||||
printf("Creating a new signature failed\n");
|
printf("Creating a new signature failed\n");
|
||||||
|
BIO_free_all(hashes);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!add_indirect_data_object(p7, hashes, ctx)) {
|
if (!add_indirect_data_object(p7)) {
|
||||||
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
BIO_free_all(hashes);
|
BIO_free_all(hashes);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(hashes, ctx);
|
||||||
|
BIO_free_all(hashes);
|
||||||
|
if (!content) {
|
||||||
|
printf("Failed to get spcIndirectDataContent\n");
|
||||||
PKCS7_free(p7);
|
PKCS7_free(p7);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
BIO_free_all(hashes);
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
|
printf("Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
return p7; /* OK */
|
return p7; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,27 +757,21 @@ static int appx_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
|||||||
* [out] outdata: outdata file BIO
|
* [out] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static BIO *appx_bio_free(BIO *hash, BIO *outdata)
|
static void appx_bio_free(BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
BIO_free_all(outdata);
|
BIO_free_all(outdata);
|
||||||
BIO_free_all(hash);
|
BIO_free_all(hash);
|
||||||
return NULL; /* OK */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate a FILE_FORMAT_CTX structure and PE format specific structure,
|
* Deallocate a FILE_FORMAT_CTX structure and PE format specific structure.
|
||||||
* unmap indata file, unlink outfile.
|
|
||||||
* [out] ctx: structure holds input and output data
|
* [out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [in] outdata: outdata file BIO
|
* [in] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static void appx_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static void appx_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (outdata) {
|
|
||||||
BIO_free_all(hash);
|
|
||||||
BIO_free_all(outdata);
|
|
||||||
}
|
|
||||||
freeZip(ctx->appx_ctx->zip);
|
freeZip(ctx->appx_ctx->zip);
|
||||||
OPENSSL_free(ctx->appx_ctx->calculatedBMHash);
|
OPENSSL_free(ctx->appx_ctx->calculatedBMHash);
|
||||||
OPENSSL_free(ctx->appx_ctx->calculatedCTHash);
|
OPENSSL_free(ctx->appx_ctx->calculatedCTHash);
|
||||||
@ -1129,7 +1196,8 @@ static int appx_remove_ct_signature_entry(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_E
|
|||||||
size_t dataSize, ipos, len;
|
size_t dataSize, ipos, len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!zipReadFileData(zip, &data, (uint64_t *)&dataSize, entry)) {
|
dataSize = zipReadFileData(zip, &data, entry);
|
||||||
|
if (dataSize <= 0) {
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
cpos = strstr((const char *)data, SIGNATURE_CONTENT_TYPES_ENTRY);
|
cpos = strstr((const char *)data, SIGNATURE_CONTENT_TYPES_ENTRY);
|
||||||
@ -1161,7 +1229,8 @@ static int appx_append_ct_signature_entry(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_E
|
|||||||
size_t dataSize, newSize, ipos, len;
|
size_t dataSize, newSize, ipos, len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!zipReadFileData(zip, &data, (uint64_t *)&dataSize, entry)) {
|
dataSize = zipReadFileData(zip, &data, entry);
|
||||||
|
if (dataSize <= 0) {
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
existingEntry = strstr((const char *)data, SIGNATURE_CONTENT_TYPES_ENTRY);
|
existingEntry = strstr((const char *)data, SIGNATURE_CONTENT_TYPES_ENTRY);
|
||||||
@ -1196,13 +1265,13 @@ static int appx_append_ct_signature_entry(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_E
|
|||||||
static const EVP_MD *appx_get_md(ZIP_FILE *zip)
|
static const EVP_MD *appx_get_md(ZIP_FILE *zip)
|
||||||
{
|
{
|
||||||
uint8_t *data = NULL;
|
uint8_t *data = NULL;
|
||||||
uint64_t dataSize = 0;
|
|
||||||
char *start, *end, *pos;
|
char *start, *end, *pos;
|
||||||
char *valueStart = NULL, *valueEnd = NULL;
|
char *valueStart = NULL, *valueEnd = NULL;
|
||||||
const EVP_MD *md = NULL;
|
const EVP_MD *md = NULL;
|
||||||
size_t slen;
|
size_t slen, dataSize;
|
||||||
|
|
||||||
if (!zipReadFileDataByName(&data, &dataSize, zip, BLOCK_MAP_FILENAME)) {
|
dataSize = zipReadFileDataByName(&data, zip, BLOCK_MAP_FILENAME);
|
||||||
|
if (dataSize <= 0) {
|
||||||
printf("Could not read: %s\n", BLOCK_MAP_FILENAME);
|
printf("Could not read: %s\n", BLOCK_MAP_FILENAME);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
@ -1527,7 +1596,7 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
|
|||||||
|
|
||||||
memset(&header, 0, sizeof(header));
|
memset(&header, 0, sizeof(header));
|
||||||
if (entry->offsetOfLocalHeader >= (uint64_t)zip->fileSize) {
|
if (entry->offsetOfLocalHeader >= (uint64_t)zip->fileSize) {
|
||||||
printf("Corrupted relative offset of local header : 0x%08lX\n", entry->offsetOfLocalHeader);
|
printf("Corrupted relative offset of local header : 0x%08" PRIX64 "\n", entry->offsetOfLocalHeader);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (fseeko(zip->file, (int64_t)entry->offsetOfLocalHeader, SEEK_SET) < 0) {
|
if (fseeko(zip->file, (int64_t)entry->offsetOfLocalHeader, SEEK_SET) < 0) {
|
||||||
@ -1548,7 +1617,7 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
|
|||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (entry->compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
|
if (entry->compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
|
||||||
printf("Corrupted compressedSize : 0x%08lX\n", entry->compressedSize);
|
printf("Corrupted compressedSize : 0x%08" PRIX64 "\n", entry->compressedSize);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (fseeko(zip->file, (int64_t)entry->compressedSize, SEEK_CUR) < 0) {
|
if (fseeko(zip->file, (int64_t)entry->compressedSize, SEEK_CUR) < 0) {
|
||||||
@ -1677,11 +1746,12 @@ static int zipEntryExist(ZIP_FILE *zip, const char *name)
|
|||||||
static u_char *zipCalcDigest(ZIP_FILE *zip, const char *fileName, const EVP_MD *md)
|
static u_char *zipCalcDigest(ZIP_FILE *zip, const char *fileName, const EVP_MD *md)
|
||||||
{
|
{
|
||||||
uint8_t *data = NULL;
|
uint8_t *data = NULL;
|
||||||
uint64_t dataSize = 0;
|
size_t dataSize;
|
||||||
u_char *mdbuf = NULL;
|
u_char *mdbuf = NULL;
|
||||||
BIO *bhash;
|
BIO *bhash;
|
||||||
|
|
||||||
if (!zipReadFileDataByName(&data, &dataSize, zip, fileName)) {
|
dataSize = zipReadFileDataByName(&data, zip, fileName);
|
||||||
|
if (dataSize <= 0) {
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
bhash = BIO_new(BIO_f_md());
|
bhash = BIO_new(BIO_f_md());
|
||||||
@ -1708,12 +1778,11 @@ static u_char *zipCalcDigest(ZIP_FILE *zip, const char *fileName, const EVP_MD *
|
|||||||
/*
|
/*
|
||||||
* Read file data by name.
|
* Read file data by name.
|
||||||
* [out] pData: pointer to data
|
* [out] pData: pointer to data
|
||||||
* [out] dataSize: data size
|
|
||||||
* [in] zip: structure holds specific ZIP data
|
* [in] zip: structure holds specific ZIP data
|
||||||
* [in] name: one of ZIP container file
|
* [in] name: one of ZIP container file
|
||||||
* [returns] 0 on error or 1 on success
|
* [returns] 0 on error or data size on success
|
||||||
*/
|
*/
|
||||||
static int zipReadFileDataByName(uint8_t **pData, uint64_t *dataSize, ZIP_FILE *zip, const char *name)
|
static size_t zipReadFileDataByName(uint8_t **pData, ZIP_FILE *zip, const char *name)
|
||||||
{
|
{
|
||||||
ZIP_CENTRAL_DIRECTORY_ENTRY *entry;
|
ZIP_CENTRAL_DIRECTORY_ENTRY *entry;
|
||||||
uint64_t noEntries = 0;
|
uint64_t noEntries = 0;
|
||||||
@ -1729,7 +1798,7 @@ static int zipReadFileDataByName(uint8_t **pData, uint64_t *dataSize, ZIP_FILE *
|
|||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!strcmp(entry->fileName, name)) {
|
if (!strcmp(entry->fileName, name)) {
|
||||||
return zipReadFileData(zip, pData, dataSize, entry);
|
return zipReadFileData(zip, pData, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
@ -1739,20 +1808,19 @@ static int zipReadFileDataByName(uint8_t **pData, uint64_t *dataSize, ZIP_FILE *
|
|||||||
* Read file data.
|
* Read file data.
|
||||||
* [in, out] zip: structure holds specific ZIP data
|
* [in, out] zip: structure holds specific ZIP data
|
||||||
* [out] pData: pointer to data
|
* [out] pData: pointer to data
|
||||||
* [out] dataSize: data size
|
|
||||||
* [in] entry: central directory structure
|
* [in] entry: central directory structure
|
||||||
* [returns] 0 on error or 1 on success
|
* [returns] 0 on error or data size on success
|
||||||
*/
|
*/
|
||||||
static int zipReadFileData(ZIP_FILE *zip, uint8_t **pData, uint64_t *dataSize, ZIP_CENTRAL_DIRECTORY_ENTRY *entry)
|
static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECTORY_ENTRY *entry)
|
||||||
{
|
{
|
||||||
FILE *file = zip->file;
|
FILE *file = zip->file;
|
||||||
uint8_t *compressedData = NULL;
|
uint8_t *compressedData = NULL;
|
||||||
uint64_t compressedSize = 0;
|
uint64_t compressedSize = 0;
|
||||||
uint64_t uncompressedSize = 0;
|
uint64_t uncompressedSize = 0;
|
||||||
size_t size;
|
size_t size, dataSize = 0;
|
||||||
|
|
||||||
if (entry->offsetOfLocalHeader >= (uint64_t)zip->fileSize) {
|
if (entry->offsetOfLocalHeader >= (uint64_t)zip->fileSize) {
|
||||||
printf("Corrupted relative offset of local header : 0x%08lX\n", entry->offsetOfLocalHeader);
|
printf("Corrupted relative offset of local header : 0x%08" PRIX64 "\n", entry->offsetOfLocalHeader);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (fseeko(file, (int64_t)entry->offsetOfLocalHeader, SEEK_SET) < 0) {
|
if (fseeko(file, (int64_t)entry->offsetOfLocalHeader, SEEK_SET) < 0) {
|
||||||
@ -1784,7 +1852,7 @@ static int zipReadFileData(ZIP_FILE *zip, uint8_t **pData, uint64_t *dataSize, Z
|
|||||||
OPENSSL_free(header.extraField);
|
OPENSSL_free(header.extraField);
|
||||||
|
|
||||||
if (compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
|
if (compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
|
||||||
printf("Corrupted compressedSize : 0x%08lX\n", entry->compressedSize);
|
printf("Corrupted compressedSize : 0x%08" PRIX64 "\n", entry->compressedSize);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
compressedData = OPENSSL_zalloc(compressedSize + 1);
|
compressedData = OPENSSL_zalloc(compressedSize + 1);
|
||||||
@ -1796,15 +1864,19 @@ static int zipReadFileData(ZIP_FILE *zip, uint8_t **pData, uint64_t *dataSize, Z
|
|||||||
compressedData[compressedSize] = 0;
|
compressedData[compressedSize] = 0;
|
||||||
}
|
}
|
||||||
if (entry->compression == COMPRESSION_NONE) {
|
if (entry->compression == COMPRESSION_NONE) {
|
||||||
|
if (compressedSize == 0) {
|
||||||
|
OPENSSL_free(compressedData);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
*pData = compressedData;
|
*pData = compressedData;
|
||||||
*dataSize = compressedSize;
|
dataSize = compressedSize;
|
||||||
} else if (entry->compression == COMPRESSION_DEFLATE) {
|
} else if (entry->compression == COMPRESSION_DEFLATE) {
|
||||||
uint8_t *uncompressedData = OPENSSL_zalloc(uncompressedSize + 1);
|
uint8_t *uncompressedData = OPENSSL_zalloc(uncompressedSize + 1);
|
||||||
uint64_t destLen = uncompressedSize;
|
uint64_t destLen = uncompressedSize;
|
||||||
uint64_t sourceLen = compressedSize;
|
uint64_t sourceLen = compressedSize;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = zipInflate(uncompressedData, &destLen, compressedData, &sourceLen);
|
ret = zipInflate(uncompressedData, &destLen, compressedData, (uLong *)&sourceLen);
|
||||||
OPENSSL_free(compressedData);
|
OPENSSL_free(compressedData);
|
||||||
|
|
||||||
if (ret != Z_OK) {
|
if (ret != Z_OK) {
|
||||||
@ -1812,15 +1884,19 @@ static int zipReadFileData(ZIP_FILE *zip, uint8_t **pData, uint64_t *dataSize, Z
|
|||||||
OPENSSL_free(uncompressedData);
|
OPENSSL_free(uncompressedData);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
} else {
|
} else {
|
||||||
|
if (destLen == 0) {
|
||||||
|
OPENSSL_free(uncompressedData);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
*pData = uncompressedData;
|
*pData = uncompressedData;
|
||||||
*dataSize = destLen;
|
dataSize = destLen;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Unsupported compression mode: %d\n", entry->compression);
|
printf("Unsupported compression mode: %d\n", entry->compression);
|
||||||
OPENSSL_free(compressedData);
|
OPENSSL_free(compressedData);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
return 1; /* OK */
|
return dataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1893,7 +1969,7 @@ static int zipReadLocalHeader(ZIP_LOCAL_HEADER *header, ZIP_FILE *zip, uint64_t
|
|||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (compressedSize > (uint64_t)(zip->fileSize - offset)) {
|
if (compressedSize > (uint64_t)(zip->fileSize - offset)) {
|
||||||
printf("Corrupted compressedSize : 0x%08lX\n", compressedSize);
|
printf("Corrupted compressedSize : 0x%08" PRIX64 "\n", compressedSize);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (fseeko(file, (int64_t)compressedSize, SEEK_CUR) < 0) {
|
if (fseeko(file, (int64_t)compressedSize, SEEK_CUR) < 0) {
|
||||||
@ -2133,7 +2209,7 @@ static ZIP_FILE *openZip(const char *filename)
|
|||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (zip->locator.eocdOffset >= (uint64_t)zip->fileSize) {
|
if (zip->locator.eocdOffset >= (uint64_t)zip->fileSize) {
|
||||||
printf("Corrupted end of central directory locator offset : 0x%08lX\n", zip->locator.eocdOffset);
|
printf("Corrupted end of central directory locator offset : 0x%08" PRIX64 "\n", zip->locator.eocdOffset);
|
||||||
freeZip(zip);
|
freeZip(zip);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
@ -2162,13 +2238,13 @@ static ZIP_FILE *openZip(const char *filename)
|
|||||||
zip->centralDirectorySize = zip->eocdr.centralDirectorySize;
|
zip->centralDirectorySize = zip->eocdr.centralDirectorySize;
|
||||||
zip->centralDirectoryRecordCount = (uint64_t)zip->eocdr.totalEntries;
|
zip->centralDirectoryRecordCount = (uint64_t)zip->eocdr.totalEntries;
|
||||||
if (zip->centralDirectoryRecordCount > UINT16_MAX) {
|
if (zip->centralDirectoryRecordCount > UINT16_MAX) {
|
||||||
printf("Corrupted total number of entries in the central directory : 0x%08lX\n", zip->centralDirectoryRecordCount);
|
printf("Corrupted total number of entries in the central directory : 0x%08" PRIX64 "\n", zip->centralDirectoryRecordCount);
|
||||||
freeZip(zip);
|
freeZip(zip);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (zip->centralDirectoryOffset >= (uint64_t)zip->fileSize) {
|
if (zip->centralDirectoryOffset >= (uint64_t)zip->fileSize) {
|
||||||
printf("Corrupted central directory offset : 0x%08lX\n", zip->centralDirectoryOffset);
|
printf("Corrupted central directory offset : 0x%08" PRIX64 "\n", zip->centralDirectoryOffset);
|
||||||
freeZip(zip);
|
freeZip(zip);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
@ -2560,7 +2636,7 @@ static int readZip64EOCDR(ZIP64_EOCDR *eocdr, FILE *file, uint64_t offset)
|
|||||||
/* zip64 extensible data sector (comment) */
|
/* zip64 extensible data sector (comment) */
|
||||||
eocdr->commentLen = eocdr->eocdrSize - 44;
|
eocdr->commentLen = eocdr->eocdrSize - 44;
|
||||||
if (eocdr->commentLen > UINT16_MAX) {
|
if (eocdr->commentLen > UINT16_MAX) {
|
||||||
printf("Corrupted file comment length : 0x%08lX\n", eocdr->commentLen);
|
printf("Corrupted file comment length : 0x%08" PRIX64 "\n", eocdr->commentLen);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (eocdr->commentLen > 0) {
|
if (eocdr->commentLen > 0) {
|
||||||
|
211
cab.c
211
cab.c
@ -43,32 +43,38 @@ struct cab_ctx_st {
|
|||||||
/* FILE_FORMAT method prototypes */
|
/* FILE_FORMAT method prototypes */
|
||||||
static FILE_FORMAT_CTX *cab_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
static FILE_FORMAT_CTX *cab_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
static ASN1_OBJECT *cab_obsolete_link_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
static ASN1_OBJECT *cab_obsolete_link_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *cab_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
static int cab_hash_length_get(FILE_FORMAT_CTX *ctx);
|
static int cab_hash_length_get(FILE_FORMAT_CTX *ctx);
|
||||||
static int cab_check_file(FILE_FORMAT_CTX *ctx, int detached);
|
|
||||||
static u_char *cab_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
static u_char *cab_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
static int cab_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
static int cab_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
static PKCS7 *cab_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
static PKCS7 *cab_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *cab_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx);
|
||||||
static int cab_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int cab_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
static PKCS7 *cab_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int cab_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static PKCS7 *cab_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
static int cab_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
static int cab_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static void cab_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
static void cab_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static BIO *cab_bio_free(BIO *hash, BIO *outdata);
|
static void cab_bio_free(BIO *hash, BIO *outdata);
|
||||||
static void cab_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static void cab_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int cab_is_detaching_supported(void);
|
||||||
|
|
||||||
FILE_FORMAT file_format_cab = {
|
FILE_FORMAT file_format_cab = {
|
||||||
.ctx_new = cab_ctx_new,
|
.ctx_new = cab_ctx_new,
|
||||||
.data_blob_get = cab_obsolete_link_get,
|
.data_blob_get = cab_obsolete_link_get,
|
||||||
|
.pkcs7_contents_get = cab_pkcs7_contents_get,
|
||||||
.hash_length_get = cab_hash_length_get,
|
.hash_length_get = cab_hash_length_get,
|
||||||
.check_file = cab_check_file,
|
|
||||||
.digest_calc = cab_digest_calc,
|
.digest_calc = cab_digest_calc,
|
||||||
.verify_digests = cab_verify_digests,
|
.verify_digests = cab_verify_digests,
|
||||||
.pkcs7_extract = cab_pkcs7_extract,
|
.pkcs7_extract = cab_pkcs7_extract,
|
||||||
|
.pkcs7_extract_to_nest = cab_pkcs7_extract_to_nest,
|
||||||
.remove_pkcs7 = cab_remove_pkcs7,
|
.remove_pkcs7 = cab_remove_pkcs7,
|
||||||
.pkcs7_prepare = cab_pkcs7_prepare,
|
.process_data = cab_process_data,
|
||||||
|
.pkcs7_signature_new = cab_pkcs7_signature_new,
|
||||||
.append_pkcs7 = cab_append_pkcs7,
|
.append_pkcs7 = cab_append_pkcs7,
|
||||||
.update_data_size = cab_update_data_size,
|
.update_data_size = cab_update_data_size,
|
||||||
.bio_free = cab_bio_free,
|
.bio_free = cab_bio_free,
|
||||||
.ctx_cleanup = cab_ctx_cleanup
|
.ctx_cleanup = cab_ctx_cleanup,
|
||||||
|
.is_detaching_supported = cab_is_detaching_supported
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
@ -77,6 +83,7 @@ static int cab_add_jp_attribute(PKCS7 *p7, int jp);
|
|||||||
static size_t cab_write_optional_names(BIO *outdata, char *indata, size_t len, uint16_t flags);
|
static size_t cab_write_optional_names(BIO *outdata, char *indata, size_t len, uint16_t flags);
|
||||||
static int cab_modify_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int cab_modify_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
static int cab_add_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int cab_add_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static int cab_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FILE_FORMAT method definitions
|
* FILE_FORMAT method definitions
|
||||||
@ -104,12 +111,12 @@ static FILE_FORMAT_CTX *cab_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (memcmp(options->indata, "MSCF", 4)) {
|
if (memcmp(options->indata, "MSCF", 4)) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
cab_ctx = cab_ctx_get(options->indata, filesize);
|
cab_ctx = cab_ctx_get(options->indata, filesize);
|
||||||
if (!cab_ctx) {
|
if (!cab_ctx) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
@ -151,6 +158,32 @@ static ASN1_OBJECT *cab_obsolete_link_get(u_char **p, int *plen, FILE_FORMAT_CTX
|
|||||||
return dtype; /* OK */
|
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 *cab_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
|
||||||
|
/* squash the unused parameter warning, use initialized message digest BIO */
|
||||||
|
(void)md;
|
||||||
|
|
||||||
|
/* Strip current signature and modify header */
|
||||||
|
if (ctx->cab_ctx->header_size == 20) {
|
||||||
|
if (!cab_modify_header(ctx, hash, NULL))
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
} else {
|
||||||
|
if (!cab_add_header(ctx, hash, NULL))
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
return pkcs7_set_content(content);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
* [returns] the size of the message digest when passed an EVP_MD structure (the size of the hash)
|
* [returns] the size of the message digest when passed an EVP_MD structure (the size of the hash)
|
||||||
@ -160,34 +193,6 @@ static int cab_hash_length_get(FILE_FORMAT_CTX *ctx)
|
|||||||
return EVP_MD_size(ctx->options->md);
|
return EVP_MD_size(ctx->options->md);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the signature exists.
|
|
||||||
* [in, out] ctx: structure holds input and output data
|
|
||||||
* [in] detached: embedded/detached PKCS#7 signature switch
|
|
||||||
* [returns] 0 on error or 1 on success
|
|
||||||
*/
|
|
||||||
static int cab_check_file(FILE_FORMAT_CTX *ctx, int detached)
|
|
||||||
{
|
|
||||||
if (!ctx) {
|
|
||||||
printf("Init error\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
if (detached) {
|
|
||||||
printf("Checking the specified catalog file\n\n");
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
|
||||||
if (ctx->cab_ctx->header_size != 20) {
|
|
||||||
printf("No signature found\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
if (ctx->cab_ctx->sigpos == 0 || ctx->cab_ctx->siglen == 0
|
|
||||||
|| ctx->cab_ctx->sigpos > ctx->cab_ctx->fileend) {
|
|
||||||
printf("No signature found\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute a message digest value of the signed or unsigned CAB file.
|
* Compute a message digest value of the signed or unsigned CAB file.
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
@ -363,11 +368,23 @@ static int cab_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|||||||
*/
|
*/
|
||||||
static PKCS7 *cab_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
static PKCS7 *cab_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->cab_ctx->sigpos == 0 || ctx->cab_ctx->siglen == 0
|
const u_char *blob;
|
||||||
|| ctx->cab_ctx->sigpos > ctx->cab_ctx->fileend) {
|
|
||||||
|
if (!cab_check_file(ctx)) {
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
return pkcs7_get(ctx->options->indata, ctx->cab_ctx->sigpos, ctx->cab_ctx->siglen);
|
blob = (u_char *)ctx->options->indata + ctx->cab_ctx->sigpos;
|
||||||
|
return d2i_PKCS7(NULL, &blob, ctx->cab_ctx->siglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *cab_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return cab_pkcs7_extract(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -382,11 +399,15 @@ static int cab_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
size_t i, written, len;
|
size_t i, written, len;
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
uint16_t nfolders, flags;
|
uint16_t nfolders, flags;
|
||||||
char *buf = OPENSSL_malloc(SIZE_64K);
|
char *buf;
|
||||||
|
|
||||||
/* squash the unused parameter warning */
|
/* squash the unused parameter warning */
|
||||||
(void)hash;
|
(void)hash;
|
||||||
|
|
||||||
|
if (!cab_check_file(ctx)) {
|
||||||
|
return 1; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
buf = OPENSSL_malloc(SIZE_64K);
|
||||||
/*
|
/*
|
||||||
* u1 signature[4] 4643534D MSCF: 0-3
|
* u1 signature[4] 4643534D MSCF: 0-3
|
||||||
* u4 reserved1 00000000: 4-7
|
* u4 reserved1 00000000: 4-7
|
||||||
@ -448,47 +469,36 @@ static int cab_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain an existing signature or create a new one.
|
* Modify specific type data and calculate a hash (message digest) of data.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [out] outdata: outdata file BIO
|
* [out] outdata: outdata file BIO
|
||||||
* [returns] pointer to PKCS#7 structure
|
* [returns] 1 on error or 0 on success
|
||||||
*/
|
*/
|
||||||
static PKCS7 *cab_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int cab_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
PKCS7 *cursig = NULL, *p7 = NULL;
|
|
||||||
|
|
||||||
/* Strip current signature and modify header */
|
/* Strip current signature and modify header */
|
||||||
if (ctx->cab_ctx->header_size == 20) {
|
if (ctx->cab_ctx->header_size == 20) {
|
||||||
if (!cab_modify_header(ctx, hash, outdata))
|
if (!cab_modify_header(ctx, hash, outdata))
|
||||||
return NULL; /* FAILED */
|
return 1; /* FAILED */
|
||||||
} else {
|
} else {
|
||||||
if (!cab_add_header(ctx, hash, outdata))
|
if (!cab_add_header(ctx, hash, outdata))
|
||||||
return NULL; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
/* Obtain a current signature from previously-signed file */
|
return 0; /* OK */
|
||||||
if ((ctx->options->cmd == CMD_SIGN && ctx->options->nest)
|
|
||||||
|| (ctx->options->cmd == CMD_ATTACH && ctx->options->nest)
|
|
||||||
|| ctx->options->cmd == CMD_ADD) {
|
|
||||||
cursig = pkcs7_get(ctx->options->indata, ctx->cab_ctx->sigpos, ctx->cab_ctx->siglen);
|
|
||||||
if (!cursig) {
|
|
||||||
printf("Unable to extract existing signature\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
}
|
||||||
if (ctx->options->cmd == CMD_ADD)
|
|
||||||
p7 = cursig;
|
/*
|
||||||
}
|
* Create a new PKCS#7 signature.
|
||||||
if (ctx->options->cmd == CMD_ATTACH) {
|
* [in, out] ctx: structure holds input and output data
|
||||||
/* Obtain an existing PKCS#7 signature */
|
* [out] hash: message digest BIO
|
||||||
p7 = pkcs7_get_sigfile(ctx);
|
* [returns] pointer to PKCS#7 structure
|
||||||
if (!p7) {
|
*/
|
||||||
printf("Unable to extract valid signature\n");
|
static PKCS7 *cab_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
PKCS7_free(cursig);
|
{
|
||||||
return NULL; /* FAILED */
|
ASN1_OCTET_STRING *content;
|
||||||
}
|
PKCS7 *p7 = pkcs7_create(ctx);
|
||||||
} else if (ctx->options->cmd == CMD_SIGN) {
|
|
||||||
/* Create a new PKCS#7 signature */
|
|
||||||
p7 = pkcs7_create(ctx);
|
|
||||||
if (!p7) {
|
if (!p7) {
|
||||||
printf("Creating a new signature failed\n");
|
printf("Creating a new signature failed\n");
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
@ -498,14 +508,23 @@ static PKCS7 *cab_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
PKCS7_free(p7);
|
PKCS7_free(p7);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!add_indirect_data_object(p7, hash, ctx)) {
|
if (!add_indirect_data_object(p7)) {
|
||||||
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
PKCS7_free(p7);
|
PKCS7_free(p7);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
if (!content) {
|
||||||
|
printf("Failed to get spcIndirectDataContent\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (ctx->options->nest)
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
ctx->options->prevsig = cursig;
|
printf("Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
return p7;
|
return p7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,40 +599,33 @@ static void cab_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
|||||||
* [out] outdata: outdata file BIO (unused)
|
* [out] outdata: outdata file BIO (unused)
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static BIO *cab_bio_free(BIO *hash, BIO *outdata)
|
static void cab_bio_free(BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
/* squash the unused parameter warning */
|
/* squash the unused parameter warning */
|
||||||
(void)outdata;
|
(void)outdata;
|
||||||
|
|
||||||
BIO_free_all(hash);
|
BIO_free_all(hash);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate a FILE_FORMAT_CTX structure and CAB format specific structure,
|
* Deallocate a FILE_FORMAT_CTX structure and CAB format specific structure,
|
||||||
* unmap indata file, unlink outfile.
|
* unmap indata file.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [in] outdata: outdata file BIO
|
* [in] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static void cab_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static void cab_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (outdata) {
|
|
||||||
BIO_free_all(hash);
|
|
||||||
if (ctx->options->outfile) {
|
|
||||||
#ifdef WIN32
|
|
||||||
_unlink(ctx->options->outfile);
|
|
||||||
#else
|
|
||||||
unlink(ctx->options->outfile);
|
|
||||||
#endif /* WIN32 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unmap_file(ctx->options->indata, ctx->cab_ctx->fileend);
|
unmap_file(ctx->options->indata, ctx->cab_ctx->fileend);
|
||||||
OPENSSL_free(ctx->cab_ctx);
|
OPENSSL_free(ctx->cab_ctx);
|
||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cab_is_detaching_supported(void)
|
||||||
|
{
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CAB helper functions
|
* CAB helper functions
|
||||||
*/
|
*/
|
||||||
@ -931,6 +943,29 @@ static int cab_add_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
return 1; /* OK */
|
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 cab_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
printf("Init error\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->cab_ctx->header_size != 20) {
|
||||||
|
printf("No signature found\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->cab_ctx->sigpos == 0 || ctx->cab_ctx->siglen == 0
|
||||||
|
|| ctx->cab_ctx->sigpos > ctx->cab_ctx->fileend) {
|
||||||
|
printf("No signature found\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
c-basic-offset: 4
|
c-basic-offset: 4
|
||||||
|
387
cat.c
387
cat.c
@ -5,34 +5,49 @@
|
|||||||
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@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.
|
* 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 "osslsigncode.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
const u_char pkcs7_signed_data[] = {
|
typedef struct {
|
||||||
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
ASN1_BMPSTRING *tag;
|
||||||
0x01, 0x07, 0x02,
|
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 {
|
struct cat_ctx_st {
|
||||||
uint32_t sigpos;
|
uint32_t sigpos;
|
||||||
uint32_t siglen;
|
uint32_t siglen;
|
||||||
uint32_t fileend;
|
uint32_t fileend;
|
||||||
|
PKCS7 *p7;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FILE_FORMAT method prototypes */
|
/* FILE_FORMAT method prototypes */
|
||||||
static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
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_extract(FILE_FORMAT_CTX *ctx);
|
||||||
static PKCS7 *cat_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
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 int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static BIO *cat_bio_free(BIO *hash, BIO *outdata);
|
static void cat_bio_free(BIO *hash, BIO *outdata);
|
||||||
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
FILE_FORMAT file_format_cat = {
|
FILE_FORMAT file_format_cat = {
|
||||||
.ctx_new = cat_ctx_new,
|
.ctx_new = cat_ctx_new,
|
||||||
|
.verify_digests = cat_verify_digests,
|
||||||
.pkcs7_extract = cat_pkcs7_extract,
|
.pkcs7_extract = cat_pkcs7_extract,
|
||||||
.pkcs7_prepare = cat_pkcs7_prepare,
|
.pkcs7_signature_new = cat_pkcs7_signature_new,
|
||||||
.append_pkcs7 = cat_append_pkcs7,
|
.append_pkcs7 = cat_append_pkcs7,
|
||||||
.bio_free = cat_bio_free,
|
.bio_free = cat_bio_free,
|
||||||
.ctx_cleanup = cat_ctx_cleanup,
|
.ctx_cleanup = cat_ctx_cleanup,
|
||||||
@ -40,6 +55,14 @@ FILE_FORMAT file_format_cat = {
|
|||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize);
|
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
|
* FILE_FORMAT method definitions
|
||||||
@ -58,18 +81,10 @@ static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
CAT_CTX *cat_ctx;
|
CAT_CTX *cat_ctx;
|
||||||
uint32_t filesize;
|
uint32_t filesize;
|
||||||
|
|
||||||
/* squash unused parameter warnings */
|
if (options->cmd == CMD_REMOVE || options->cmd==CMD_ATTACH || options->cmd == CMD_EXTRACT_DATA) {
|
||||||
(void)outdata;
|
|
||||||
(void)hash;
|
|
||||||
|
|
||||||
if (options->cmd == CMD_REMOVE || options->cmd==CMD_ATTACH) {
|
|
||||||
printf("Unsupported command\n");
|
printf("Unsupported command\n");
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (options->cmd == CMD_VERIFY) {
|
|
||||||
printf("Use -catalog option\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
filesize = get_file_size(options->infile);
|
filesize = get_file_size(options->infile);
|
||||||
if (filesize == 0)
|
if (filesize == 0)
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
@ -78,15 +93,9 @@ static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
if (!options->indata) {
|
if (!options->indata) {
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
/* the maximum size of a supported cat file is (2^24 -1) bytes */
|
|
||||||
if (memcmp(options->indata + ((GET_UINT8_LE(options->indata+1) == 0x82) ? 4 : 5),
|
|
||||||
pkcs7_signed_data, sizeof pkcs7_signed_data)) {
|
|
||||||
unmap_file(options->infile, filesize);
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
cat_ctx = cat_ctx_get(options->indata, filesize);
|
cat_ctx = cat_ctx_get(options->indata, filesize);
|
||||||
if (!cat_ctx) {
|
if (!cat_ctx) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
@ -97,9 +106,8 @@ static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
/* Push hash on outdata, if hash is NULL the function does nothing */
|
/* Push hash on outdata, if hash is NULL the function does nothing */
|
||||||
BIO_push(hash, outdata);
|
BIO_push(hash, outdata);
|
||||||
|
|
||||||
if (options->nest)
|
if (options->cmd == CMD_VERIFY)
|
||||||
/* I've not tried using set_nested_signature as signtool won't do this */
|
printf("Warning: Use -catalog option to verify that a file, listed in catalog file, is signed\n");
|
||||||
printf("Warning: CAT files do not support nesting (multiple signature)\n");
|
|
||||||
if (options->jp >= 0)
|
if (options->jp >= 0)
|
||||||
printf("Warning: -jp option is only valid for CAB files\n");
|
printf("Warning: -jp option is only valid for CAB files\n");
|
||||||
if (options->pagehash == 1)
|
if (options->pagehash == 1)
|
||||||
@ -109,6 +117,19 @@ static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
return ctx;
|
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.
|
* Extract existing signature in DER format.
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
@ -116,76 +137,53 @@ static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
*/
|
*/
|
||||||
static PKCS7 *cat_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
static PKCS7 *cat_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
return pkcs7_get(ctx->options->indata, ctx->cat_ctx->sigpos, ctx->cat_ctx->siglen);
|
if (!cat_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return PKCS7_dup(ctx->cat_ctx->p7);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain an existing signature or create a new one.
|
* Create a new PKCS#7 signature.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO (unused)
|
* [out] hash: message digest BIO (unused)
|
||||||
* [out] outdata: outdata file BIO (unused)
|
|
||||||
* [returns] pointer to PKCS#7 structure
|
* [returns] pointer to PKCS#7 structure
|
||||||
*/
|
*/
|
||||||
static PKCS7 *cat_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static PKCS7 *cat_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
{
|
{
|
||||||
PKCS7 *cursig = NULL, *p7 = NULL;
|
PKCS7 *p7 = NULL;
|
||||||
|
|
||||||
/* squash unused parameter warnings */
|
/* squash unused parameter warnings */
|
||||||
(void)outdata;
|
|
||||||
(void)hash;
|
(void)hash;
|
||||||
|
|
||||||
/* Obtain an existing signature */
|
|
||||||
cursig = pkcs7_get(ctx->options->indata, ctx->cat_ctx->sigpos, ctx->cat_ctx->siglen);
|
|
||||||
if (!cursig) {
|
|
||||||
printf("Unable to extract existing signature\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
if (ctx->options->cmd == CMD_ADD || ctx->options->cmd == CMD_ATTACH) {
|
|
||||||
p7 = cursig;
|
|
||||||
} else if (ctx->options->cmd == CMD_SIGN) {
|
|
||||||
/* Create a new signature */
|
|
||||||
p7 = pkcs7_create(ctx);
|
p7 = pkcs7_create(ctx);
|
||||||
if (!p7) {
|
if (!p7) {
|
||||||
printf("Creating a new signature failed\n");
|
printf("Creating a new signature failed\n");
|
||||||
PKCS7_free(cursig);
|
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!add_ms_ctl_object(p7, cursig)) {
|
if (!cat_add_ms_ctl_object(p7)) {
|
||||||
printf("Adding MS_CTL_OBJID failed\n");
|
printf("Adding MS_CTL_OBJID failed\n");
|
||||||
PKCS7_free(p7);
|
PKCS7_free(p7);
|
||||||
PKCS7_free(cursig);
|
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
PKCS7_free(cursig);
|
if (!cat_sign_ms_ctl_content(p7, ctx->cat_ctx->p7->d.sign->contents)) {
|
||||||
|
printf("Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
return p7; /* OK */
|
return p7; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append signature to the outfile.
|
* Append signature to the outfile.
|
||||||
* [in, out] ctx: structure holds input and output data (unused)
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] outdata: outdata file BIO
|
* [out] outdata: outdata file BIO
|
||||||
* [in] p7: PKCS#7 signature
|
* [in] p7: PKCS#7 signature
|
||||||
* [returns] 1 on error or 0 on success
|
* [returns] 1 on error or 0 on success
|
||||||
*/
|
*/
|
||||||
static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
{
|
{
|
||||||
u_char *p = NULL;
|
return data_write_pkcs7(ctx, outdata, p7);
|
||||||
int len; /* signature length */
|
|
||||||
|
|
||||||
/* squash the unused parameter warning */
|
|
||||||
(void)ctx;
|
|
||||||
|
|
||||||
if (((len = i2d_PKCS7(p7, NULL)) <= 0)
|
|
||||||
|| (p = OPENSSL_malloc((size_t)len)) == NULL) {
|
|
||||||
printf("i2d_PKCS memory allocation failed: %d\n", len);
|
|
||||||
return 1; /* FAILED */
|
|
||||||
}
|
|
||||||
i2d_PKCS7(p7, &p);
|
|
||||||
p -= len;
|
|
||||||
i2d_PKCS7_bio(outdata, p7);
|
|
||||||
OPENSSL_free(p);
|
|
||||||
return 0; /* OK */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -194,36 +192,25 @@ static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
|||||||
* [out] outdata: outdata file BIO (unused)
|
* [out] outdata: outdata file BIO (unused)
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static BIO *cat_bio_free(BIO *hash, BIO *outdata)
|
static void cat_bio_free(BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
/* squash the unused parameter warning */
|
/* squash the unused parameter warning */
|
||||||
(void)outdata;
|
(void)outdata;
|
||||||
|
|
||||||
BIO_free_all(hash);
|
BIO_free_all(hash);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate a FILE_FORMAT_CTX structure and CAT format specific structure,
|
* Deallocate a FILE_FORMAT_CTX structure and CAT format specific structure,
|
||||||
* unmap indata file, unlink outfile.
|
* unmap indata file.
|
||||||
* [in, out] ctx: structure holds all input and output data
|
* [in, out] ctx: structure holds all input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [in] outdata: outdata file BIO
|
* [in] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (outdata) {
|
|
||||||
BIO_free_all(hash);
|
|
||||||
if (ctx->options->outfile) {
|
|
||||||
#ifdef WIN32
|
|
||||||
_unlink(ctx->options->outfile);
|
|
||||||
#else
|
|
||||||
unlink(ctx->options->outfile);
|
|
||||||
#endif /* WIN32 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unmap_file(ctx->options->indata, ctx->cat_ctx->fileend);
|
unmap_file(ctx->options->indata, ctx->cat_ctx->fileend);
|
||||||
|
PKCS7_free(ctx->cat_ctx->p7);
|
||||||
OPENSSL_free(ctx->cat_ctx);
|
OPENSSL_free(ctx->cat_ctx);
|
||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
}
|
}
|
||||||
@ -233,25 +220,255 @@ static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify mapped CAT file TODO and create CAT format specific structure.
|
* Verify mapped PKCS#7 (CAT) file and create CAT format specific structure.
|
||||||
* [in] indata: mapped CAT file (unused)
|
* [in] indata: mapped file
|
||||||
* [in] filesize: size of CAT file
|
* [in] filesize: size of file
|
||||||
* [returns] pointer to CAT format specific structure
|
* [returns] pointer to CAT format specific structure
|
||||||
*/
|
*/
|
||||||
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize)
|
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize)
|
||||||
{
|
{
|
||||||
CAT_CTX *cat_ctx;
|
CAT_CTX *cat_ctx;
|
||||||
|
PKCS7 *p7;
|
||||||
|
|
||||||
/* squash the unused parameter warning */
|
p7 = pkcs7_read_data(indata, filesize);
|
||||||
(void)indata;
|
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 = OPENSSL_zalloc(sizeof(CAT_CTX));
|
||||||
|
cat_ctx->p7 = p7;
|
||||||
cat_ctx->sigpos = 0;
|
cat_ctx->sigpos = 0;
|
||||||
cat_ctx->siglen = filesize;
|
cat_ctx->siglen = filesize;
|
||||||
cat_ctx->fileend = filesize;
|
cat_ctx->fileend = filesize;
|
||||||
return cat_ctx; /* OK */
|
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;
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
printf("Failed to sign content\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!PKCS7_set_content(p7, PKCS7_dup(contents))) {
|
||||||
|
printf("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) {
|
||||||
|
printf("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(stdout);
|
||||||
|
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) {
|
||||||
|
printf("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) {
|
||||||
|
printf("Init error\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
signer_info = PKCS7_get_signer_info(ctx->cat_ctx->p7);
|
||||||
|
if (!signer_info) {
|
||||||
|
printf("Failed catalog file\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si) {
|
||||||
|
printf("No signature found\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->options->verbose) {
|
||||||
|
(void)cat_list_content(ctx->cat_ctx->p7);
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
c-basic-offset: 4
|
c-basic-offset: 4
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
option(STOP_SERVER "Stop HTTP server after tests" ON)
|
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})
|
||||||
|
|
||||||
include(FindPython3)
|
include(FindPython3)
|
||||||
|
|
||||||
set(TEST_DIR "${PROJECT_BINARY_DIR}/Testing")
|
set(TEST_DIR "${PROJECT_BINARY_DIR}/Testing")
|
||||||
@ -70,6 +74,8 @@ else(WIN32 OR APPLE)
|
|||||||
RESULT_VARIABLE server_error)
|
RESULT_VARIABLE server_error)
|
||||||
if(server_error)
|
if(server_error)
|
||||||
message(STATUS "HTTP server failed: ${server_error}")
|
message(STATUS "HTTP server failed: ${server_error}")
|
||||||
|
message(STATUS "Use python3 to start HTTP server: \"python3 Testing/server_http.py --port 19254\"")
|
||||||
|
set(default_certs 1)
|
||||||
else(server_error)
|
else(server_error)
|
||||||
# Check if file exists and is no-empty
|
# Check if file exists and is no-empty
|
||||||
while(NOT EXISTS ${LOGS}/port.log)
|
while(NOT EXISTS ${LOGS}/port.log)
|
||||||
@ -123,9 +129,10 @@ string(SUBSTRING ${sha256sum} 0 64 leafhash)
|
|||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
set(extensions_all "exe" "ex_" "msi" "256appx" "512appx" "cat")
|
set(extensions_all "exe" "ex_" "msi" "256appx" "512appx" "cat" "ps1" "psc1" "mof")
|
||||||
set(extensions_nocat "exe" "ex_" "msi" "256appx" "512appx")
|
set(extensions_nocat "exe" "ex_" "msi" "256appx" "512appx" "ps1" "psc1" "mof")
|
||||||
set(extensions_nocatappx "exe" "ex_" "msi")
|
set(extensions_nocatappx "exe" "ex_" "msi" "ps1" "psc1" "mof")
|
||||||
|
set(formats "pem" "der")
|
||||||
|
|
||||||
# Test 1
|
# Test 1
|
||||||
# Print osslsigncode version
|
# Print osslsigncode version
|
||||||
@ -134,7 +141,7 @@ add_test(NAME version
|
|||||||
|
|
||||||
### Sign ###
|
### Sign ###
|
||||||
|
|
||||||
# Tests 2-5
|
# Tests 2-7
|
||||||
# Sign with PKCS#12 container with legacy RC2-40-CBC private key and certificate encryption algorithm
|
# Sign with PKCS#12 container with legacy RC2-40-CBC private key and certificate encryption algorithm
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
@ -142,7 +149,7 @@ foreach(ext ${extensions_all})
|
|||||||
COMMAND osslsigncode "sign"
|
COMMAND osslsigncode "sign"
|
||||||
"-pkcs12" "${CERTS}/legacy.p12"
|
"-pkcs12" "${CERTS}/legacy.p12"
|
||||||
"-readpass" "${CERTS}/password.txt"
|
"-readpass" "${CERTS}/password.txt"
|
||||||
"-ac" "${CERTS}/crosscert.pem"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
"-add-msi-dse"
|
"-add-msi-dse"
|
||||||
"-comm"
|
"-comm"
|
||||||
@ -154,7 +161,7 @@ foreach(ext ${extensions_all})
|
|||||||
"-out" "${FILES}/legacy.${ext}")
|
"-out" "${FILES}/legacy.${ext}")
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 6-9
|
# Tests 8-13
|
||||||
# Sign with PKCS#12 container with legacy RC2-40-CBC private key and certificate encryption algorithm
|
# Sign with PKCS#12 container with legacy RC2-40-CBC private key and certificate encryption algorithm
|
||||||
# Disable legacy mode and don't automatically load the legacy provider
|
# Disable legacy mode and don't automatically load the legacy provider
|
||||||
# Option "-nolegacy" requires OpenSSL 3.0.0 or later
|
# Option "-nolegacy" requires OpenSSL 3.0.0 or later
|
||||||
@ -167,7 +174,7 @@ if(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.0.0)
|
|||||||
"-pkcs12" "${CERTS}/legacy.p12"
|
"-pkcs12" "${CERTS}/legacy.p12"
|
||||||
"-readpass" "${CERTS}/password.txt"
|
"-readpass" "${CERTS}/password.txt"
|
||||||
"-nolegacy" # Disable legacy mode
|
"-nolegacy" # Disable legacy mode
|
||||||
"-ac" "${CERTS}/crosscert.pem"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
"-add-msi-dse"
|
"-add-msi-dse"
|
||||||
"-comm"
|
"-comm"
|
||||||
@ -184,7 +191,7 @@ if(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.0.0)
|
|||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
endif(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.0.0)
|
endif(OPENSSL_VERSION VERSION_GREATER_EQUAL 3.0.0)
|
||||||
|
|
||||||
# Tests 10-13
|
# Tests 14-19
|
||||||
# Sign with PKCS#12 container with AES-256-CBC private key and certificate encryption algorithm
|
# Sign with PKCS#12 container with AES-256-CBC private key and certificate encryption algorithm
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
@ -192,7 +199,7 @@ foreach(ext ${extensions_all})
|
|||||||
COMMAND osslsigncode "sign"
|
COMMAND osslsigncode "sign"
|
||||||
"-pkcs12" "${CERTS}/cert.p12"
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
"-readpass" "${CERTS}/password.txt"
|
"-readpass" "${CERTS}/password.txt"
|
||||||
"-ac" "${CERTS}/crosscert.pem"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
"-add-msi-dse"
|
"-add-msi-dse"
|
||||||
"-comm"
|
"-comm"
|
||||||
@ -204,7 +211,7 @@ foreach(ext ${extensions_all})
|
|||||||
"-out" "${FILES}/signed.${ext}")
|
"-out" "${FILES}/signed.${ext}")
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 14-17
|
# Tests 20-25
|
||||||
# Sign with revoked certificate
|
# Sign with revoked certificate
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
@ -213,7 +220,7 @@ foreach(ext ${extensions_all})
|
|||||||
"-certs" "${CERTS}/revoked.pem"
|
"-certs" "${CERTS}/revoked.pem"
|
||||||
"-key" "${CERTS}/keyp.pem"
|
"-key" "${CERTS}/keyp.pem"
|
||||||
"-readpass" "${CERTS}/password.txt"
|
"-readpass" "${CERTS}/password.txt"
|
||||||
"-ac" "${CERTS}/crosscert.pem"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
"-add-msi-dse"
|
"-add-msi-dse"
|
||||||
"-comm"
|
"-comm"
|
||||||
@ -225,7 +232,7 @@ foreach(ext ${extensions_all})
|
|||||||
"-out" "${FILES}/revoked.${ext}")
|
"-out" "${FILES}/revoked.${ext}")
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 18-20
|
# Tests 26-30
|
||||||
# Remove signature
|
# Remove signature
|
||||||
# Unsupported command for CAT files
|
# Unsupported command for CAT files
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_nocat})
|
||||||
@ -241,7 +248,7 @@ foreach(ext ${extensions_nocat})
|
|||||||
REQUIRED_FILES "${FILES}/signed.${ext}")
|
REQUIRED_FILES "${FILES}/signed.${ext}")
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
# Tests 21-24
|
# Tests 31-36
|
||||||
# Extract PKCS#7 signature in PEM format
|
# Extract PKCS#7 signature in PEM format
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
@ -257,7 +264,7 @@ foreach(ext ${extensions_all})
|
|||||||
REQUIRED_FILES "${FILES}/signed.${ext}")
|
REQUIRED_FILES "${FILES}/signed.${ext}")
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 25-28
|
# Tests 37-42
|
||||||
# Extract PKCS#7 signature in default DER format
|
# Extract PKCS#7 signature in default DER format
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
@ -272,17 +279,15 @@ foreach(ext ${extensions_all})
|
|||||||
REQUIRED_FILES "${FILES}/signed.${ext}")
|
REQUIRED_FILES "${FILES}/signed.${ext}")
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 29-34
|
# Tests 43-52
|
||||||
# Attach signature in PEM or DER format
|
# Attach a nested signature in PEM or DER format
|
||||||
# Unsupported command for CAT files
|
# Unsupported command for CAT files
|
||||||
set(formats "pem" "der")
|
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_nocat})
|
||||||
foreach(format ${formats})
|
foreach(format ${formats})
|
||||||
add_test(
|
add_test(
|
||||||
NAME attached_${format}_${ext}
|
NAME attached_${format}_${ext}
|
||||||
COMMAND osslsigncode "attach-signature"
|
COMMAND osslsigncode "attach-signature"
|
||||||
# sign options
|
# sign options
|
||||||
"-time" "1567296000" # Signing and signature verification time: Sep 1 00:00:00 2019 GMT
|
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
"-require-leaf-hash" "SHA256:${leafhash}"
|
||||||
"-add-msi-dse"
|
"-add-msi-dse"
|
||||||
"-h" "sha512"
|
"-h" "sha512"
|
||||||
@ -291,6 +296,7 @@ foreach(ext ${extensions_nocat})
|
|||||||
"-in" "${FILES}/signed.${ext}"
|
"-in" "${FILES}/signed.${ext}"
|
||||||
"-out" "${FILES}/attached_${format}.${ext}"
|
"-out" "${FILES}/attached_${format}.${ext}"
|
||||||
# verify options
|
# verify options
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
"-CAfile" "${CERTS}/CACert.pem"
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
"-CRLfile" "${CERTS}/CACertCRL.pem")
|
"-CRLfile" "${CERTS}/CACertCRL.pem")
|
||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
@ -302,7 +308,7 @@ foreach(ext ${extensions_nocat})
|
|||||||
endforeach(format ${formats})
|
endforeach(format ${formats})
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
# Tests 35-38
|
# Tests 53-58
|
||||||
# Add an unauthenticated blob to a previously-signed file
|
# Add an unauthenticated blob to a previously-signed file
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
@ -319,8 +325,9 @@ foreach(ext ${extensions_all})
|
|||||||
REQUIRED_FILES "${FILES}/signed.${ext}")
|
REQUIRED_FILES "${FILES}/signed.${ext}")
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 39-42
|
# Tests 59-64
|
||||||
# Add the new nested signature instead of replacing the first one
|
# Add the new nested signature instead of replacing the first one
|
||||||
|
# APPX files do not support nesting (multiple signature)
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
NAME nested_${ext}
|
NAME nested_${ext}
|
||||||
@ -329,8 +336,8 @@ foreach(ext ${extensions_all})
|
|||||||
"-certs" "${CERTS}/cert.pem"
|
"-certs" "${CERTS}/cert.pem"
|
||||||
"-key" "${CERTS}/key.der"
|
"-key" "${CERTS}/key.der"
|
||||||
"-pass" "passme"
|
"-pass" "passme"
|
||||||
"-ac" "${CERTS}/crosscert.pem"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
"-time" "1556755200" # Signing time: May 2 00:00:00 2019 GMT
|
||||||
"-add-msi-dse"
|
"-add-msi-dse"
|
||||||
"-comm"
|
"-comm"
|
||||||
"-ph"
|
"-ph"
|
||||||
@ -350,9 +357,9 @@ endforeach(ext ${extensions_all})
|
|||||||
|
|
||||||
### Verify signature ###
|
### Verify signature ###
|
||||||
|
|
||||||
# Tests 43-45
|
# Tests 65-67
|
||||||
# Verify PE/MSI/CAB files signed in the catalog file
|
# Verify PE/MSI/CAB files signed in the catalog file
|
||||||
# APPX does not support detached PKCS#7 signature
|
# CAT and APPX files do not support detached PKCS#7 signature
|
||||||
foreach(ext ${extensions_nocatappx})
|
foreach(ext ${extensions_nocatappx})
|
||||||
add_test(
|
add_test(
|
||||||
NAME verify_catalog_${ext}
|
NAME verify_catalog_${ext}
|
||||||
@ -371,9 +378,64 @@ foreach(ext ${extensions_nocatappx})
|
|||||||
REQUIRED_FILES "${FILES}/unsigned.${ext}")
|
REQUIRED_FILES "${FILES}/unsigned.${ext}")
|
||||||
endforeach(ext ${extensions_nocatappx})
|
endforeach(ext ${extensions_nocatappx})
|
||||||
|
|
||||||
# Tests 46-69
|
# Tests 68-97
|
||||||
# Verify signature
|
# Verify signature
|
||||||
set(files "legacy" "signed" "nested" "added" "removed" "revoked" "attached_pem" "attached_der")
|
set(files "legacy" "signed" "nested" "added" "revoked")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(
|
||||||
|
NAME verify_${file}_${ext}
|
||||||
|
COMMAND 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}"
|
||||||
|
REQUIRED_FILES "${FILES}/${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})
|
||||||
|
|
||||||
|
# Tests 98-102
|
||||||
|
# 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 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}"
|
||||||
|
REQUIRED_FILES "${FILES}/${file}.${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# Tests 103-112
|
||||||
|
# Verify attached signature
|
||||||
|
# "attach-signature" command is unsupported for CAT files
|
||||||
|
set(files "attached_pem" "attached_der")
|
||||||
foreach(file ${files})
|
foreach(file ${files})
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_nocat})
|
||||||
add_test(
|
add_test(
|
||||||
@ -391,22 +453,12 @@ foreach(file ${files})
|
|||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_nocat})
|
||||||
endforeach(file ${files})
|
endforeach(file ${files})
|
||||||
|
|
||||||
# "Removed" and "revoked" tests are expected to fail
|
|
||||||
set(files "removed" "revoked")
|
|
||||||
foreach(file ${files})
|
|
||||||
foreach(ext ${extensions_nocat})
|
|
||||||
set_tests_properties(
|
|
||||||
verify_${file}_${ext}
|
|
||||||
PROPERTIES
|
|
||||||
WILL_FAIL TRUE)
|
|
||||||
endforeach(ext ${extensions_nocat})
|
|
||||||
endforeach(file ${files})
|
|
||||||
|
|
||||||
if(Python3_FOUND OR server_error)
|
if((Python3_FOUND OR server_error) AND CURL_FOUND)
|
||||||
|
|
||||||
### Sign with Time-Stamp Authority ###
|
### Sign with Time-Stamp Authority ###
|
||||||
|
|
||||||
# Tests 70-89
|
# Tests 113-142
|
||||||
# Sign with the RFC3161 Time-Stamp Authority
|
# Sign with the RFC3161 Time-Stamp Authority
|
||||||
# Use "cert" "expired" "revoked" without X509v3 CRL Distribution Points extension
|
# Use "cert" "expired" "revoked" without X509v3 CRL Distribution Points extension
|
||||||
# and "cert_crldp" "revoked_crldp" contain X509v3 CRL Distribution Points extension
|
# and "cert_crldp" "revoked_crldp" contain X509v3 CRL Distribution Points extension
|
||||||
@ -418,7 +470,7 @@ if(Python3_FOUND OR server_error)
|
|||||||
COMMAND osslsigncode "sign"
|
COMMAND osslsigncode "sign"
|
||||||
"-certs" "${CERTS}/${cert}.pem"
|
"-certs" "${CERTS}/${cert}.pem"
|
||||||
"-key" "${CERTS}/key.pem"
|
"-key" "${CERTS}/key.pem"
|
||||||
"-ac" "${CERTS}/crosscert.pem"
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
"-comm"
|
"-comm"
|
||||||
"-ph"
|
"-ph"
|
||||||
"-jp" "low"
|
"-jp" "low"
|
||||||
@ -432,6 +484,7 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
sign_ts_${cert}_${ext}
|
sign_ts_${cert}_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
REQUIRED_FILES "${LOGS}/port.log")
|
REQUIRED_FILES "${LOGS}/port.log")
|
||||||
endforeach(cert ${pem_certs})
|
endforeach(cert ${pem_certs})
|
||||||
endforeach(ext ${extensions_all})
|
endforeach(ext ${extensions_all})
|
||||||
@ -439,9 +492,9 @@ if(Python3_FOUND OR server_error)
|
|||||||
|
|
||||||
### Verify Time-Stamp Authority ###
|
### Verify Time-Stamp Authority ###
|
||||||
|
|
||||||
# Tests 90-92
|
# Tests 143-148
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
NAME verify_ts_cert_${ext}
|
NAME verify_ts_cert_${ext}
|
||||||
COMMAND osslsigncode "verify"
|
COMMAND osslsigncode "verify"
|
||||||
@ -452,14 +505,15 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
verify_ts_cert_${ext}
|
verify_ts_cert_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
DEPENDS "sign_ts_cert_${ext}"
|
DEPENDS "sign_ts_cert_${ext}"
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
||||||
REQUIRED_FILES "${LOGS}/port.log")
|
REQUIRED_FILES "${LOGS}/port.log")
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 93-95
|
# Tests 149-154
|
||||||
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
NAME verify_ts_future_${ext}
|
NAME verify_ts_future_${ext}
|
||||||
COMMAND osslsigncode "verify"
|
COMMAND osslsigncode "verify"
|
||||||
@ -470,15 +524,16 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
verify_ts_future_${ext}
|
verify_ts_future_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
DEPENDS "sign_ts_cert_${ext}"
|
DEPENDS "sign_ts_cert_${ext}"
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
||||||
REQUIRED_FILES "${LOGS}/port.log")
|
REQUIRED_FILES "${LOGS}/port.log")
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 96-98
|
# Tests 155-160
|
||||||
# Verify with ignored timestamp
|
# Verify with ignored timestamp
|
||||||
# This tests are expected to fail
|
# This tests are expected to fail
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
NAME verify_ts_ignore_${ext}
|
NAME verify_ts_ignore_${ext}
|
||||||
COMMAND osslsigncode "verify"
|
COMMAND osslsigncode "verify"
|
||||||
@ -490,20 +545,21 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
verify_ts_ignore_${ext}
|
verify_ts_ignore_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
DEPENDS "sign_ts_cert_${ext}"
|
DEPENDS "sign_ts_cert_${ext}"
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
||||||
REQUIRED_FILES "${LOGS}/port.log"
|
REQUIRED_FILES "${LOGS}/port.log"
|
||||||
WILL_FAIL TRUE)
|
WILL_FAIL TRUE)
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
### Verify CRL Distribution Points ###
|
### Verify CRL Distribution Points ###
|
||||||
|
|
||||||
# Tests 99-101
|
# Tests 161-166
|
||||||
# Verify file signed with X509v3 CRL Distribution Points extension
|
# 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
|
||||||
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
NAME verify_ts_cert_crldp_${ext}
|
NAME verify_ts_cert_crldp_${ext}
|
||||||
COMMAND osslsigncode "verify"
|
COMMAND osslsigncode "verify"
|
||||||
@ -514,16 +570,17 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
verify_ts_cert_crldp_${ext}
|
verify_ts_cert_crldp_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
DEPENDS "sign_ts_cert_crldp_${ext}"
|
DEPENDS "sign_ts_cert_crldp_${ext}"
|
||||||
REQUIRED_FILES "${FILES}/ts_cert_crldp.${ext}"
|
REQUIRED_FILES "${FILES}/ts_cert_crldp.${ext}"
|
||||||
REQUIRED_FILES "${LOGS}/port.log")
|
REQUIRED_FILES "${LOGS}/port.log")
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 102-107
|
# Tests 167-183
|
||||||
# Verify with expired or revoked certificate without X509v3 CRL Distribution Points extension
|
# Verify with expired or revoked certificate without X509v3 CRL Distribution Points extension
|
||||||
# This tests are expected to fail
|
# This tests are expected to fail
|
||||||
set(failed_certs "expired" "revoked")
|
set(failed_certs "expired" "revoked")
|
||||||
foreach(ext ${extensions_nocat})
|
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}
|
||||||
@ -536,18 +593,19 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
verify_ts_${cert}_${ext}
|
verify_ts_${cert}_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
DEPENDS "sign_ts_${cert}_${ext}"
|
DEPENDS "sign_ts_${cert}_${ext}"
|
||||||
REQUIRED_FILES "${FILES}/ts_${cert}.${ext}"
|
REQUIRED_FILES "${FILES}/ts_${cert}.${ext}"
|
||||||
REQUIRED_FILES "${LOGS}/port.log"
|
REQUIRED_FILES "${LOGS}/port.log"
|
||||||
WILL_FAIL TRUE)
|
WILL_FAIL TRUE)
|
||||||
endforeach(cert ${failed_certs})
|
endforeach(cert ${failed_certs})
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
# Tests 108-110
|
# Tests 178-184
|
||||||
# Verify with revoked certificate contains X509v3 CRL Distribution Points extension
|
# Verify with revoked certificate contains X509v3 CRL Distribution Points extension
|
||||||
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
||||||
# This test is expected to fail
|
# This test is expected to fail
|
||||||
foreach(ext ${extensions_nocat})
|
foreach(ext ${extensions_all})
|
||||||
add_test(
|
add_test(
|
||||||
NAME verify_ts_revoked_crldp_${ext}
|
NAME verify_ts_revoked_crldp_${ext}
|
||||||
COMMAND osslsigncode "verify"
|
COMMAND osslsigncode "verify"
|
||||||
@ -558,16 +616,102 @@ if(Python3_FOUND OR server_error)
|
|||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
verify_ts_revoked_crldp_${ext}
|
verify_ts_revoked_crldp_${ext}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
DEPENDS "sign_ts_revoked_crldp_${ext}"
|
DEPENDS "sign_ts_revoked_crldp_${ext}"
|
||||||
REQUIRED_FILES "${FILES}/ts_revoked_crldp.${ext}"
|
REQUIRED_FILES "${FILES}/ts_revoked_crldp.${ext}"
|
||||||
REQUIRED_FILES "${LOGS}/port.log"
|
REQUIRED_FILES "${LOGS}/port.log"
|
||||||
WILL_FAIL TRUE)
|
WILL_FAIL TRUE)
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Tests 185-234
|
||||||
|
# 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 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 osslsigncode "extract-data"
|
||||||
|
"-ph"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/data_${ext}.der")
|
||||||
|
|
||||||
|
# Sign a data content, output in DER format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
add_test(
|
||||||
|
NAME signed_data_${ext}_${data_format}
|
||||||
|
COMMAND 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")
|
||||||
|
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 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")
|
||||||
|
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 osslsigncode "attach-signature"
|
||||||
|
# sign options
|
||||||
|
"-require-leaf-hash" "SHA256:${leafhash}"
|
||||||
|
"-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
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem")
|
||||||
|
set_tests_properties(
|
||||||
|
attached_${format}_${ext}
|
||||||
|
PROPERTIES
|
||||||
|
DEPENDS "signed_data_${ext}_${data_format}:data_${ext}_${format}")
|
||||||
|
endforeach(format ${formats})
|
||||||
|
endforeach(data_format ${formats})
|
||||||
endforeach(ext ${extensions_nocat})
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
|
|
||||||
### Cleanup ###
|
### Cleanup ###
|
||||||
|
|
||||||
# Test 111
|
|
||||||
# Stop HTTP server
|
# Stop HTTP server
|
||||||
if(STOP_SERVER)
|
if(STOP_SERVER)
|
||||||
add_test(NAME stop_server
|
add_test(NAME stop_server
|
||||||
@ -580,21 +724,16 @@ if(Python3_FOUND OR server_error)
|
|||||||
message(STATUS "Keep HTTP server after tests")
|
message(STATUS "Keep HTTP server after tests")
|
||||||
endif(STOP_SERVER)
|
endif(STOP_SERVER)
|
||||||
|
|
||||||
else(Python3_FOUND OR server_error)
|
else((Python3_FOUND OR server_error) AND CURL_FOUND)
|
||||||
message(STATUS "CTest skips some tests")
|
message(STATUS "CTest skips some tests")
|
||||||
endif(Python3_FOUND OR server_error)
|
endif((Python3_FOUND OR server_error) AND CURL_FOUND)
|
||||||
|
|
||||||
|
|
||||||
# Test 112
|
|
||||||
# Delete test files
|
# Delete test files
|
||||||
|
set(names "legacy" "signed" "signed_crldp" "nested" "revoked" "removed" "added")
|
||||||
foreach(ext ${extensions_all})
|
foreach(ext ${extensions_all})
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/legacy.${ext}")
|
foreach(name ${names})
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/signed.${ext}")
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${name}.${ext}")
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/signed_crldp.${ext}")
|
endforeach(name ${names})
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/nested.${ext}")
|
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/revoked.${ext}")
|
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/removed.${ext}")
|
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/added.${ext}")
|
|
||||||
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(cert ${pem_certs})
|
endforeach(cert ${pem_certs})
|
||||||
@ -602,6 +741,11 @@ foreach(ext ${extensions_all})
|
|||||||
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}")
|
||||||
|
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})
|
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")
|
||||||
|
608
helpers.c
608
helpers.c
@ -9,12 +9,14 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
static int pkcs7_set_content_blob(PKCS7 *sig, PKCS7 *cursig);
|
|
||||||
static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx);
|
static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx);
|
||||||
static int spc_indirect_data_content_get(u_char **blob, int *len, FILE_FORMAT_CTX *ctx);
|
static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT_CTX *ctx);
|
||||||
static int pkcs7_set_spc_indirect_data_content(PKCS7 *p7, BIO *hash, u_char *buf, 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_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_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
|
* Common functions
|
||||||
@ -109,113 +111,52 @@ void unmap_file(char *indata, const size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in, out] si: PKCS7_SIGNER_INFO structure
|
* Retrieve a decoded PKCS#7 structure
|
||||||
* [in] ctx: FILE_FORMAT_CTX structure
|
* [in] data: encoded PEM or DER data
|
||||||
* [returns] 0 on error or 1 on success
|
* [in] size: data size
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* [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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve a decoded PKCS#7 structure corresponding to the signature
|
|
||||||
* stored in the "sigin" file
|
|
||||||
* CMD_ATTACH command specific
|
|
||||||
* [in] ctx: structure holds input and output data
|
|
||||||
* [returns] pointer to PKCS#7 structure
|
* [returns] pointer to PKCS#7 structure
|
||||||
*/
|
*/
|
||||||
PKCS7 *pkcs7_get_sigfile(FILE_FORMAT_CTX *ctx)
|
PKCS7 *pkcs7_read_data(char *data, uint32_t size)
|
||||||
{
|
{
|
||||||
PKCS7 *p7 = NULL;
|
PKCS7 *p7 = NULL;
|
||||||
uint32_t filesize;
|
|
||||||
char *indata;
|
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
const char pemhdr[] = "-----BEGIN PKCS7-----";
|
const char pemhdr[] = "-----BEGIN PKCS7-----";
|
||||||
|
|
||||||
filesize = get_file_size(ctx->options->sigfile);
|
bio = BIO_new_mem_buf(data, (int)size);
|
||||||
if (!filesize) {
|
if (size >= sizeof pemhdr && !memcmp(data, pemhdr, sizeof pemhdr - 1)) {
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
indata = map_file(ctx->options->sigfile, filesize);
|
|
||||||
if (!indata) {
|
|
||||||
printf("Failed to open file: %s\n", ctx->options->sigfile);
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
bio = BIO_new_mem_buf(indata, (int)filesize);
|
|
||||||
if (filesize >= sizeof pemhdr && !memcmp(indata, pemhdr, sizeof pemhdr - 1)) {
|
|
||||||
/* PEM format */
|
/* PEM format */
|
||||||
p7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
|
p7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
|
||||||
} else { /* DER format */
|
} else { /* DER format */
|
||||||
p7 = d2i_PKCS7_bio(bio, NULL);
|
p7 = d2i_PKCS7_bio(bio, NULL);
|
||||||
}
|
}
|
||||||
BIO_free_all(bio);
|
BIO_free_all(bio);
|
||||||
unmap_file(indata, filesize);
|
|
||||||
return p7;
|
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) {
|
||||||
|
printf("Unable to write pkcs7 object\n");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate, set type, add content and return a new PKCS#7 signature
|
* Allocate, set type, add content and return a new PKCS#7 signature
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
@ -226,10 +167,11 @@ PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
|
|||||||
int i, signer = -1;
|
int i, signer = -1;
|
||||||
PKCS7 *p7;
|
PKCS7 *p7;
|
||||||
PKCS7_SIGNER_INFO *si = NULL;
|
PKCS7_SIGNER_INFO *si = NULL;
|
||||||
|
STACK_OF(X509) *chain = NULL;
|
||||||
|
|
||||||
p7 = PKCS7_new();
|
p7 = PKCS7_new();
|
||||||
PKCS7_set_type(p7, NID_pkcs7_signed);
|
PKCS7_set_type(p7, NID_pkcs7_signed);
|
||||||
|
PKCS7_content_new(p7, NID_pkcs7_data);
|
||||||
if (ctx->options->cert != NULL) {
|
if (ctx->options->cert != NULL) {
|
||||||
/*
|
/*
|
||||||
* the private key and corresponding certificate are parsed from the PKCS12
|
* the private key and corresponding certificate are parsed from the PKCS12
|
||||||
@ -258,50 +200,47 @@ PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
|
|||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pkcs7_signer_info_add_signing_time(si, ctx);
|
if (!pkcs7_signer_info_add_signing_time(si, ctx)) {
|
||||||
|
|
||||||
if (!pkcs7_signer_info_add_purpose(si, ctx))
|
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!pkcs7_signer_info_add_purpose(si, ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
if ((ctx->options->desc || ctx->options->url) &&
|
if ((ctx->options->desc || ctx->options->url) &&
|
||||||
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
|
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
|
||||||
printf("Couldn't allocate memory for opus info\n");
|
printf("Couldn't allocate memory for opus info\n");
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
PKCS7_content_new(p7, NID_pkcs7_data);
|
if ((ctx->options->nested_number >= 0) &&
|
||||||
|
!pkcs7_signer_info_add_sequence_number(si, ctx)) {
|
||||||
/* add the signer's certificate */
|
return NULL; /* FAILED */
|
||||||
if (ctx->options->cert != NULL)
|
|
||||||
PKCS7_add_certificate(p7, ctx->options->cert);
|
|
||||||
if (signer != -1)
|
|
||||||
PKCS7_add_certificate(p7, sk_X509_value(ctx->options->certs, signer));
|
|
||||||
|
|
||||||
/* add the certificate chain */
|
|
||||||
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
|
|
||||||
if (i == signer)
|
|
||||||
continue;
|
|
||||||
PKCS7_add_certificate(p7, sk_X509_value(ctx->options->certs, i));
|
|
||||||
}
|
}
|
||||||
/* add all cross certificates */
|
/* create X509 chain sorted in ascending order by their DER encoding */
|
||||||
if (ctx->options->xcerts) {
|
chain = X509_chain_get_sorted(ctx, signer);
|
||||||
for (i=0; i<sk_X509_num(ctx->options->xcerts); i++)
|
if (chain == NULL) {
|
||||||
PKCS7_add_certificate(p7, sk_X509_value(ctx->options->xcerts, i));
|
printf("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 */
|
/* add crls */
|
||||||
if (ctx->options->crls) {
|
if (ctx->options->crls) {
|
||||||
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
|
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
|
||||||
PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
|
PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
|
||||||
}
|
}
|
||||||
|
sk_X509_free(chain);
|
||||||
return p7; /* OK */
|
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
|
* [in, out] p7: new PKCS#7 signature
|
||||||
* [in] hash: message digest BIO
|
|
||||||
* [in] ctx: structure holds input and output data
|
|
||||||
* [returns] 0 on error or 1 on success
|
* [returns] 0 on error or 1 on success
|
||||||
*/
|
*/
|
||||||
int add_indirect_data_object(PKCS7 *p7, BIO *hash, FILE_FORMAT_CTX *ctx)
|
int add_indirect_data_object(PKCS7 *p7)
|
||||||
{
|
{
|
||||||
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
PKCS7_SIGNER_INFO *si;
|
PKCS7_SIGNER_INFO *si;
|
||||||
@ -315,67 +254,151 @@ int add_indirect_data_object(PKCS7 *p7, BIO *hash, FILE_FORMAT_CTX *ctx)
|
|||||||
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
|
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
|
||||||
V_ASN1_OBJECT, OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1)))
|
V_ASN1_OBJECT, OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1)))
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
if (!pkcs7_set_data_content(p7, hash, ctx)) {
|
return 1; /* OK */
|
||||||
printf("Signing failed\n");
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)) {
|
||||||
|
printf("Failed to sign spcIndirectDataContent\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
td7 = PKCS7_new();
|
||||||
|
if (!td7) {
|
||||||
|
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)) {
|
||||||
|
printf("PKCS7_set_content failed\n");
|
||||||
|
PKCS7_free(td7);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
return 1; /* OK */
|
return 1; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in, out] p7: new PKCS#7 signature
|
* Add encapsulated content to signed PKCS7 structure.
|
||||||
* [in] cursig: current PKCS#7 signature
|
* [in] content: spcIndirectDataContent
|
||||||
* [returns] 0 on error or 1 on success
|
* [returns] new PKCS#7 signature with encapsulated content
|
||||||
*/
|
*/
|
||||||
int add_ms_ctl_object(PKCS7 *p7, PKCS7 *cursig)
|
PKCS7 *pkcs7_set_content(ASN1_OCTET_STRING *content)
|
||||||
{
|
{
|
||||||
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
PKCS7 *p7, *td7;
|
||||||
PKCS7_SIGNER_INFO *si;
|
|
||||||
|
|
||||||
signer_info = PKCS7_get_signer_info(p7);
|
p7 = PKCS7_new();
|
||||||
if (!signer_info)
|
if (!p7) {
|
||||||
return 0; /* FAILED */
|
return NULL; /* 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 */
|
|
||||||
if (!pkcs7_set_content_blob(p7, cursig)) {
|
|
||||||
printf("Signing failed\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
}
|
||||||
return 1; /* OK */
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pkcs7_set_content_blob(PKCS7 *sig, PKCS7 *cursig)
|
/*
|
||||||
|
* 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)
|
||||||
{
|
{
|
||||||
PKCS7 *contents;
|
ASN1_OCTET_STRING *content;
|
||||||
u_char *content;
|
u_char mdbuf[5 * EVP_MAX_MD_SIZE + 24];
|
||||||
int seqhdrlen, content_length;
|
int mdlen, hashlen, len = 0;
|
||||||
BIO *sigbio;
|
u_char *data, *p = NULL;
|
||||||
|
|
||||||
contents = cursig->d.sign->contents;
|
content = ASN1_OCTET_STRING_new();
|
||||||
seqhdrlen = asn1_simple_hdr_len(contents->d.other->value.sequence->data,
|
if (!content) {
|
||||||
contents->d.other->value.sequence->length);
|
return NULL; /* FAILED */
|
||||||
content = contents->d.other->value.sequence->data + seqhdrlen;
|
}
|
||||||
content_length = contents->d.other->value.sequence->length - seqhdrlen;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if ((sigbio = PKCS7_dataInit(sig, NULL)) == NULL) {
|
/*
|
||||||
|
* 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) {
|
||||||
printf("PKCS7_dataInit failed\n");
|
printf("PKCS7_dataInit failed\n");
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
BIO_write(sigbio, content, content_length);
|
BIO_write(p7bio, data, len);
|
||||||
(void)BIO_flush(sigbio);
|
(void)BIO_flush(p7bio);
|
||||||
if (!PKCS7_dataFinal(sig, sigbio)) {
|
if (!PKCS7_dataFinal(p7, p7bio)) {
|
||||||
printf("PKCS7_dataFinal failed\n");
|
printf("PKCS7_dataFinal failed\n");
|
||||||
|
BIO_free_all(p7bio);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
BIO_free_all(sigbio);
|
BIO_free_all(p7bio);
|
||||||
if (!PKCS7_set_content(sig, PKCS7_dup(contents))) {
|
|
||||||
printf("PKCS7_set_content failed\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
return 1; /* OK */
|
return 1; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,29 +479,42 @@ int is_content_type(PKCS7 *p7, const char *objid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [out] p7: new PKCS#7 signature
|
* [in] p7: new PKCS#7 signature
|
||||||
* [in] hash: message digest BIO
|
* [returns] pointer to MsCtlContent structure
|
||||||
* [in] ctx: structure holds input and output data
|
|
||||||
* [returns] 0 on error or 1 on success
|
|
||||||
*/
|
*/
|
||||||
int pkcs7_set_data_content(PKCS7 *p7, BIO *hash, FILE_FORMAT_CTX *ctx)
|
MsCtlContent *ms_ctl_content_get(PKCS7 *p7)
|
||||||
{
|
{
|
||||||
u_char *p = NULL;
|
ASN1_STRING *value;
|
||||||
int len = 0;
|
const u_char *data;
|
||||||
u_char *buf;
|
|
||||||
|
|
||||||
if (!spc_indirect_data_content_get(&p, &len, ctx))
|
if (!is_content_type(p7, MS_CTL_OBJID)) {
|
||||||
return 0; /* FAILED */
|
printf("Failed to find MS_CTL_OBJID\n");
|
||||||
buf = OPENSSL_malloc(SIZE_64K);
|
return NULL; /* FAILED */
|
||||||
memcpy(buf, p, (size_t)len);
|
}
|
||||||
OPENSSL_free(p);
|
value = p7->d.sign->contents->d.other->value.sequence;
|
||||||
if (!pkcs7_set_spc_indirect_data_content(p7, hash, buf, len, ctx)) {
|
data = ASN1_STRING_get0_data(value);
|
||||||
OPENSSL_free(buf);
|
return d2i_MsCtlContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
}
|
||||||
OPENSSL_free(buf);
|
|
||||||
|
|
||||||
return 1; /* OK */
|
/*
|
||||||
|
* [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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -503,23 +539,6 @@ SpcLink *spc_link_obsolete_get(void)
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve a decoded PKCS#7 structure
|
|
||||||
* [in] indata: mapped file
|
|
||||||
* [in] sigpos: signature data offset
|
|
||||||
* [in] siglen: signature data size
|
|
||||||
* [returns] pointer to PKCS#7 structure
|
|
||||||
*/
|
|
||||||
PKCS7 *pkcs7_get(char *indata, uint32_t sigpos, uint32_t siglen)
|
|
||||||
{
|
|
||||||
PKCS7 *p7 = NULL;
|
|
||||||
const u_char *blob;
|
|
||||||
|
|
||||||
blob = (u_char *)indata + sigpos;
|
|
||||||
p7 = d2i_PKCS7(NULL, &blob, siglen);
|
|
||||||
return p7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in] mdbuf, cmdbuf: message digests
|
* [in] mdbuf, cmdbuf: message digests
|
||||||
* [in] mdtype: message digest algorithm type
|
* [in] mdtype: message digest algorithm type
|
||||||
@ -570,14 +589,22 @@ static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx)
|
|||||||
* [in] ctx: FILE_FORMAT_CTX structure
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
* [returns] 0 on error or 1 on success
|
* [returns] 0 on error or 1 on success
|
||||||
*/
|
*/
|
||||||
static int spc_indirect_data_content_get(u_char **blob, int *len, FILE_FORMAT_CTX *ctx)
|
static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
u_char *p = NULL;
|
u_char *p = NULL;
|
||||||
int hashlen, l = 0;
|
int mdtype, hashlen, l = 0;
|
||||||
int mdtype = EVP_MD_nid(ctx->options->md);
|
|
||||||
void *hash;
|
void *hash;
|
||||||
SpcIndirectDataContent *idc = SpcIndirectDataContent_new();
|
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 = ASN1_TYPE_new();
|
||||||
idc->data->value->type = V_ASN1_SEQUENCE;
|
idc->data->value->type = V_ASN1_SEQUENCE;
|
||||||
idc->data->value->value.sequence = ASN1_STRING_new();
|
idc->data->value->value.sequence = ASN1_STRING_new();
|
||||||
@ -603,56 +630,169 @@ static int spc_indirect_data_content_get(u_char **blob, int *len, FILE_FORMAT_CT
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace the data part with the MS Authenticode spcIndirectDataContent blob
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
* [out] p7: new PKCS#7 signature
|
|
||||||
* [in] hash: message digest BIO
|
|
||||||
* [in] blob: SpcIndirectDataContent data
|
|
||||||
* [in] len: SpcIndirectDataContent data length
|
|
||||||
* [in] ctx: FILE_FORMAT_CTX structure
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
* [returns] 0 on error or 1 on success
|
* [returns] 0 on error or 1 on success
|
||||||
*/
|
*/
|
||||||
static int pkcs7_set_spc_indirect_data_content(PKCS7 *p7, BIO *hash, u_char *buf, int len, FILE_FORMAT_CTX *ctx)
|
static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
u_char mdbuf[5 * EVP_MAX_MD_SIZE + 24];
|
SpcSpOpusInfo *opus;
|
||||||
int mdlen, seqhdrlen, hashlen;
|
ASN1_STRING *astr;
|
||||||
BIO *bio;
|
int len;
|
||||||
PKCS7 *td7;
|
u_char *p = NULL;
|
||||||
|
|
||||||
hashlen = ctx->format->hash_length_get(ctx);
|
opus = spc_sp_opus_info_create(ctx);
|
||||||
if (hashlen > EVP_MAX_MD_SIZE) {
|
if ((len = i2d_SpcSpOpusInfo(opus, NULL)) <= 0
|
||||||
/* APPX format specific */
|
|| (p = OPENSSL_malloc((size_t)len)) == NULL) {
|
||||||
mdlen = BIO_read(hash, (char*)mdbuf, hashlen);
|
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 {
|
} else {
|
||||||
mdlen = BIO_gets(hash, (char*)mdbuf, EVP_MAX_MD_SIZE);
|
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);
|
||||||
}
|
}
|
||||||
memcpy(buf + len, mdbuf, (size_t)mdlen);
|
|
||||||
seqhdrlen = asn1_simple_hdr_len(buf, len);
|
|
||||||
|
|
||||||
if ((bio = PKCS7_dataInit(p7, NULL)) == NULL) {
|
/*
|
||||||
printf("PKCS7_dataInit failed\n");
|
* [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 0; /* FAILED */
|
||||||
}
|
}
|
||||||
BIO_write(bio, buf + seqhdrlen, len - seqhdrlen + mdlen);
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(PKCS9_SEQUENCE_NUMBER),
|
||||||
(void)BIO_flush(bio);
|
V_ASN1_INTEGER, number);
|
||||||
|
|
||||||
if (!PKCS7_dataFinal(p7, bio)) {
|
|
||||||
printf("PKCS7_dataFinal failed\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
}
|
||||||
BIO_free_all(bio);
|
|
||||||
|
|
||||||
td7 = PKCS7_new();
|
/*
|
||||||
td7->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1);
|
* Create certificate chain sorted in ascending order by their DER encoding.
|
||||||
td7->d.other = ASN1_TYPE_new();
|
* [in] ctx: structure holds input and output data
|
||||||
td7->d.other->type = V_ASN1_SEQUENCE;
|
* [in] signer: signer's certificate number in the certificate chain
|
||||||
td7->d.other->value.sequence = ASN1_STRING_new();
|
* [returns] sorted certificate chain
|
||||||
ASN1_STRING_set(td7->d.other->value.sequence, buf, len + mdlen);
|
*/
|
||||||
if (!PKCS7_set_content(p7, td7)) {
|
static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
|
||||||
PKCS7_free(td7);
|
{
|
||||||
printf("PKCS7_set_content failed\n");
|
int i;
|
||||||
return 0; /* FAILED */
|
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;
|
||||||
}
|
}
|
||||||
return 1; /* OK */
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
16
helpers.h
16
helpers.h
@ -9,19 +9,21 @@
|
|||||||
uint32_t get_file_size(const char *infile);
|
uint32_t get_file_size(const char *infile);
|
||||||
char *map_file(const char *infile, const size_t size);
|
char *map_file(const char *infile, const size_t size);
|
||||||
void unmap_file(char *indata, const size_t size);
|
void unmap_file(char *indata, const size_t size);
|
||||||
int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
PKCS7 *pkcs7_read_data(char *indata, uint32_t size);
|
||||||
PKCS7 *pkcs7_get_sigfile(FILE_FORMAT_CTX *ctx);
|
int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx);
|
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx);
|
||||||
void add_content_type(PKCS7 *p7);
|
int add_indirect_data_object(PKCS7 *p7);
|
||||||
int add_indirect_data_object(PKCS7 *p7, BIO *hash, FILE_FORMAT_CTX *ctx);
|
int sign_spc_indirect_data_content(PKCS7 *p7, ASN1_OCTET_STRING *content);
|
||||||
int add_ms_ctl_object(PKCS7 *p7, PKCS7 *cursig);
|
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 asn1_simple_hdr_len(const u_char *p, int len);
|
||||||
int bio_hash_data(BIO *hash, char *indata, size_t idx, size_t fileend);
|
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);
|
void print_hash(const char *descript1, const char *descript2, const u_char *hashbuf, int length);
|
||||||
int is_content_type(PKCS7 *p7, const char *objid);
|
int is_content_type(PKCS7 *p7, const char *objid);
|
||||||
int pkcs7_set_data_content(PKCS7 *sig, BIO *hash, FILE_FORMAT_CTX *ctx);
|
MsCtlContent *ms_ctl_content_get(PKCS7 *p7);
|
||||||
|
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
|
||||||
SpcLink *spc_link_obsolete_get(void);
|
SpcLink *spc_link_obsolete_get(void);
|
||||||
PKCS7 *pkcs7_get(char *indata, uint32_t sigpos, uint32_t siglen);
|
|
||||||
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
|
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
441
msi.c
441
msi.c
@ -100,30 +100,6 @@ static const u_char msi_zeroes[] = {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
ASN1_SEQUENCE(SpcSipInfo) = {
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, a, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, string, ASN1_OCTET_STRING),
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, b, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, c, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, d, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, e, ASN1_INTEGER),
|
|
||||||
ASN1_SIMPLE(SpcSipInfo, f, ASN1_INTEGER),
|
|
||||||
} ASN1_SEQUENCE_END(SpcSipInfo)
|
|
||||||
|
|
||||||
IMPLEMENT_ASN1_FUNCTIONS(SpcSipInfo)
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_char signature[8]; /* 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 */
|
u_char signature[8]; /* 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 */
|
||||||
u_char unused_clsid[16]; /* reserved and unused */
|
u_char unused_clsid[16]; /* reserved and unused */
|
||||||
@ -215,44 +191,50 @@ struct msi_ctx_st {
|
|||||||
/* FILE_FORMAT method prototypes */
|
/* FILE_FORMAT method prototypes */
|
||||||
static FILE_FORMAT_CTX *msi_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
static FILE_FORMAT_CTX *msi_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
static ASN1_OBJECT *msi_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
static ASN1_OBJECT *msi_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *msi_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
static int msi_hash_length_get(FILE_FORMAT_CTX *ctx);
|
static int msi_hash_length_get(FILE_FORMAT_CTX *ctx);
|
||||||
static int msi_check_file(FILE_FORMAT_CTX *ctx, int detached);
|
|
||||||
static u_char *msi_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
static u_char *msi_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
static int msi_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
static int msi_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
static PKCS7 *msi_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
static PKCS7 *msi_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *msi_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx);
|
||||||
static int msi_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int msi_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
static PKCS7 *msi_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int msi_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static PKCS7 *msi_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
static int msi_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
static int msi_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static BIO *msi_bio_free(BIO *hash, BIO *outdata);
|
static void msi_bio_free(BIO *hash, BIO *outdata);
|
||||||
static void msi_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static void msi_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int msi_is_detaching_supported(void);
|
||||||
|
|
||||||
FILE_FORMAT file_format_msi = {
|
FILE_FORMAT file_format_msi = {
|
||||||
.ctx_new = msi_ctx_new,
|
.ctx_new = msi_ctx_new,
|
||||||
.data_blob_get = msi_spc_sip_info_get,
|
.data_blob_get = msi_spc_sip_info_get,
|
||||||
|
.pkcs7_contents_get = msi_pkcs7_contents_get,
|
||||||
.hash_length_get = msi_hash_length_get,
|
.hash_length_get = msi_hash_length_get,
|
||||||
.check_file = msi_check_file,
|
|
||||||
.digest_calc = msi_digest_calc,
|
.digest_calc = msi_digest_calc,
|
||||||
.verify_digests = msi_verify_digests,
|
.verify_digests = msi_verify_digests,
|
||||||
.pkcs7_extract = msi_pkcs7_extract,
|
.pkcs7_extract = msi_pkcs7_extract,
|
||||||
|
.pkcs7_extract_to_nest = msi_pkcs7_extract_to_nest,
|
||||||
.remove_pkcs7 = msi_remove_pkcs7,
|
.remove_pkcs7 = msi_remove_pkcs7,
|
||||||
.pkcs7_prepare = msi_pkcs7_prepare,
|
.process_data = msi_process_data,
|
||||||
|
.pkcs7_signature_new = msi_pkcs7_signature_new,
|
||||||
.append_pkcs7 = msi_append_pkcs7,
|
.append_pkcs7 = msi_append_pkcs7,
|
||||||
.bio_free = msi_bio_free,
|
.bio_free = msi_bio_free,
|
||||||
.ctx_cleanup = msi_ctx_cleanup
|
.ctx_cleanup = msi_ctx_cleanup,
|
||||||
|
.is_detaching_supported = msi_is_detaching_supported
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
static MSI_CTX *msi_ctx_get(char *indata, uint32_t filesize);
|
static MSI_CTX *msi_ctx_get(char *indata, uint32_t filesize);
|
||||||
static PKCS7 *msi_pkcs7_get_digital_signature(FILE_FORMAT_CTX *ctx, MSI_ENTRY *ds,
|
static PKCS7 *msi_pkcs7_get_digital_signature(FILE_FORMAT_CTX *ctx, MSI_ENTRY *ds);
|
||||||
char **p, uint32_t len);
|
|
||||||
static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent);
|
static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent);
|
||||||
static int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p_msi, uint32_t len_msi,
|
static int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p_msi, uint32_t len_msi,
|
||||||
u_char *p_msiex, uint32_t len_msiex, BIO *outdata);
|
u_char *p_msiex, uint32_t len_msiex, BIO *outdata);
|
||||||
static MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
|
static MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
|
||||||
static int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer, uint32_t len);
|
static int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer, uint32_t len);
|
||||||
static int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLen);
|
static int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLen);
|
||||||
|
static BIO *msi_digest_calc_bio(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
static int msi_calc_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, BIO *hash);
|
static int msi_calc_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
static int msi_check_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, MSI_ENTRY *dse);
|
static int msi_check_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, MSI_ENTRY *dse, PKCS7 *p7);
|
||||||
static int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root);
|
static int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root);
|
||||||
static MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi);
|
static MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi);
|
||||||
static void msi_file_free(MSI_FILE *msi);
|
static void msi_file_free(MSI_FILE *msi);
|
||||||
@ -260,6 +242,7 @@ static MSI_FILE *msi_file_new(char *buffer, uint32_t len);
|
|||||||
static int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret);
|
static int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret);
|
||||||
static void msi_dirent_free(MSI_DIRENT *dirent);
|
static void msi_dirent_free(MSI_DIRENT *dirent);
|
||||||
static int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
|
static int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
|
||||||
|
static int msi_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FILE_FORMAT method definitions
|
* FILE_FORMAT method definitions
|
||||||
@ -290,12 +273,12 @@ static FILE_FORMAT_CTX *msi_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (memcmp(options->indata, msi_magic, sizeof msi_magic)) {
|
if (memcmp(options->indata, msi_magic, sizeof msi_magic)) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
msi_ctx = msi_ctx_get(options->indata, filesize);
|
msi_ctx = msi_ctx_get(options->indata, filesize);
|
||||||
if (!msi_ctx) {
|
if (!msi_ctx) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
@ -315,6 +298,10 @@ static FILE_FORMAT_CTX *msi_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate and return SpcSipInfo object.
|
* 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.
|
||||||
* [out] p: SpcSipInfo data
|
* [out] p: SpcSipInfo data
|
||||||
* [out] plen: SpcSipInfo data length
|
* [out] plen: SpcSipInfo data length
|
||||||
* [in] ctx: structure holds input and output data (unused)
|
* [in] ctx: structure holds input and output data (unused)
|
||||||
@ -322,7 +309,7 @@ static FILE_FORMAT_CTX *msi_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *out
|
|||||||
*/
|
*/
|
||||||
static ASN1_OBJECT *msi_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx)
|
static ASN1_OBJECT *msi_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
const u_char msistr[] = {
|
const u_char SpcUUIDSipInfoMsi[] = {
|
||||||
0xf1, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0xf1, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46
|
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46
|
||||||
};
|
};
|
||||||
@ -338,7 +325,7 @@ static ASN1_OBJECT *msi_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX
|
|||||||
ASN1_INTEGER_set(si->d, 0);
|
ASN1_INTEGER_set(si->d, 0);
|
||||||
ASN1_INTEGER_set(si->e, 0);
|
ASN1_INTEGER_set(si->e, 0);
|
||||||
ASN1_INTEGER_set(si->f, 0);
|
ASN1_INTEGER_set(si->f, 0);
|
||||||
ASN1_OCTET_STRING_set(si->string, msistr, sizeof msistr);
|
ASN1_OCTET_STRING_set(si->string, SpcUUIDSipInfoMsi, sizeof SpcUUIDSipInfoMsi);
|
||||||
*plen = i2d_SpcSipInfo(si, NULL);
|
*plen = i2d_SpcSipInfo(si, NULL);
|
||||||
*p = OPENSSL_malloc((size_t)*plen);
|
*p = OPENSSL_malloc((size_t)*plen);
|
||||||
i2d_SpcSipInfo(si, p);
|
i2d_SpcSipInfo(si, p);
|
||||||
@ -349,74 +336,29 @@ static ASN1_OBJECT *msi_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Allocate and return a data content to be signed.
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
* [returns] the size of the message digest when passed an EVP_MD structure (the size of the hash)
|
* [in] hash: message digest BIO
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] data content
|
||||||
*/
|
*/
|
||||||
static int msi_hash_length_get(FILE_FORMAT_CTX *ctx)
|
static PKCS7 *msi_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md)
|
||||||
{
|
{
|
||||||
return EVP_MD_size(ctx->options->md);
|
ASN1_OCTET_STRING *content;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* squash the unused parameter warning, use initialized message digest BIO */
|
||||||
* Get DigitalSignature and MsiDigitalSignatureEx streams,
|
(void)md;
|
||||||
* check if the signature exists.
|
|
||||||
* [in, out] ctx: structure holds input and output data
|
|
||||||
* [in] detached: embedded/detached PKCS#7 signature switch (unused)
|
|
||||||
* [returns] 0 on error or 1 on successs
|
|
||||||
*/
|
|
||||||
static int msi_check_file(FILE_FORMAT_CTX *ctx, int detached)
|
|
||||||
{
|
|
||||||
char *indata = NULL;
|
|
||||||
uint32_t inlen;
|
|
||||||
MSI_ENTRY *ds, *dse = NULL;
|
|
||||||
|
|
||||||
/* squash the unused parameter warning */
|
if (ctx->options->add_msi_dse && !msi_calc_MsiDigitalSignatureEx(ctx, hash)) {
|
||||||
(void)detached;
|
printf("Unable to calc MsiDigitalSignatureEx\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
if (!ctx) {
|
|
||||||
printf("Init error\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
}
|
||||||
if (detached) {
|
if (!msi_hash_dir(ctx->msi_ctx->msi, ctx->msi_ctx->dirent, hash, 1)) {
|
||||||
printf("Checking the specified catalog file\n\n");
|
printf("Unable to msi_handle_dir()\n");
|
||||||
return 1; /* OK */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
ds = msi_signatures_get(ctx->msi_ctx->dirent, &dse);
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
if (!ds) {
|
return pkcs7_set_content(content);
|
||||||
printf("MSI file has no signature\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
inlen = GET_UINT32_LE(ds->size);
|
|
||||||
if (inlen == 0 || inlen >= MAXREGSECT) {
|
|
||||||
printf("Corrupted DigitalSignature stream length 0x%08X\n", inlen);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
indata = OPENSSL_malloc((size_t)inlen);
|
|
||||||
if (!msi_file_read(ctx->msi_ctx->msi, ds, 0, indata, inlen)) {
|
|
||||||
printf("DigitalSignature stream data error\n\n");
|
|
||||||
OPENSSL_free(indata);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
if (!dse) {
|
|
||||||
printf("Warning: MsiDigitalSignatureEx stream doesn't exist\n");
|
|
||||||
} else {
|
|
||||||
ctx->msi_ctx->len_msiex = GET_UINT32_LE(dse->size);
|
|
||||||
if (ctx->msi_ctx->len_msiex == 0 || ctx->msi_ctx->len_msiex >= MAXREGSECT) {
|
|
||||||
printf("Corrupted MsiDigitalSignatureEx stream length 0x%08X\n",
|
|
||||||
ctx->msi_ctx->len_msiex);
|
|
||||||
OPENSSL_free(indata);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
ctx->msi_ctx->p_msiex = OPENSSL_malloc((size_t)ctx->msi_ctx->len_msiex);
|
|
||||||
if (!msi_file_read(ctx->msi_ctx->msi, dse, 0, (char *)ctx->msi_ctx->p_msiex,
|
|
||||||
ctx->msi_ctx->len_msiex)) {
|
|
||||||
printf("MsiDigitalSignatureEx stream data error\n\n");
|
|
||||||
OPENSSL_free(indata);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OPENSSL_free(indata);
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -554,21 +496,54 @@ static int msi_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
|||||||
static PKCS7 *msi_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
static PKCS7 *msi_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
PKCS7 *p7;
|
PKCS7 *p7;
|
||||||
uint32_t len;
|
MSI_ENTRY *ds;
|
||||||
char *p;
|
|
||||||
|
if (!msi_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
ds = msi_signatures_get(ctx->msi_ctx->dirent, NULL);
|
||||||
|
|
||||||
MSI_ENTRY *ds = msi_signatures_get(ctx->msi_ctx->dirent, NULL);
|
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
|
printf("MSI file has no signature\n");
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
len = GET_UINT32_LE(ds->size);
|
p7 = msi_pkcs7_get_digital_signature(ctx, ds);
|
||||||
if (len == 0 || len >= MAXREGSECT) {
|
if (!p7) {
|
||||||
printf("Corrupted DigitalSignature stream length 0x%08X\n", len);
|
printf("Unable to extract existing signature\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* Perform a sanity check for the MsiDigitalSignatureEx section.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *msi_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
PKCS7 *p7;
|
||||||
|
MSI_ENTRY *ds, *dse = NULL;
|
||||||
|
|
||||||
|
if (!msi_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
ds = msi_signatures_get(ctx->msi_ctx->dirent, &dse);
|
||||||
|
if (!ds) {
|
||||||
|
printf("MSI file has no signature\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
p7 = msi_pkcs7_get_digital_signature(ctx, ds);
|
||||||
|
if (!p7) {
|
||||||
|
printf("Unable to extract existing signature\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
/* perform a sanity check for the MsiDigitalSignatureEx section */
|
||||||
|
if (!msi_check_MsiDigitalSignatureEx(ctx, dse, p7)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
p = OPENSSL_malloc((size_t)len);
|
|
||||||
p7 = msi_pkcs7_get_digital_signature(ctx, ds, &p, len);
|
|
||||||
OPENSSL_free(p);
|
|
||||||
return p7;
|
return p7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,9 +556,15 @@ static PKCS7 *msi_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
|||||||
*/
|
*/
|
||||||
static int msi_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int msi_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
|
MSI_ENTRY *ds;
|
||||||
|
|
||||||
/* squash the unused parameter warning */
|
/* squash the unused parameter warning */
|
||||||
(void)hash;
|
(void)hash;
|
||||||
|
|
||||||
|
ds = msi_signatures_get(ctx->msi_ctx->dirent, NULL);
|
||||||
|
if (!ds) {
|
||||||
|
return 1; /* FAILED, no signature */
|
||||||
|
}
|
||||||
if (!msi_dirent_delete(ctx->msi_ctx->dirent, digital_signature_ex,
|
if (!msi_dirent_delete(ctx->msi_ctx->dirent, digital_signature_ex,
|
||||||
sizeof digital_signature_ex)) {
|
sizeof digital_signature_ex)) {
|
||||||
return 1; /* FAILED */
|
return 1; /* FAILED */
|
||||||
@ -601,81 +582,56 @@ static int msi_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain an existing signature or create a new one.
|
* Calculate a hash (message digest) of data.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [out] outdata: outdata file BIO (unused)
|
* [out] outdata: outdata file BIO (unused)
|
||||||
* [returns] pointer to PKCS#7 structure
|
* [returns] 1 on error or 0 on success
|
||||||
*/
|
*/
|
||||||
static PKCS7 *msi_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int msi_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
PKCS7 *cursig = NULL, *p7 = NULL;
|
|
||||||
uint32_t len;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
/* squash the unused parameter warning */
|
/* squash the unused parameter warning */
|
||||||
(void)outdata;
|
(void)outdata;
|
||||||
|
|
||||||
if (ctx->options->add_msi_dse && !msi_calc_MsiDigitalSignatureEx(ctx, hash)) {
|
hash = msi_digest_calc_bio(ctx, hash);
|
||||||
printf("Unable to calc MsiDigitalSignatureEx\n");
|
if (!hash) {
|
||||||
return NULL; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!msi_hash_dir(ctx->msi_ctx->msi, ctx->msi_ctx->dirent, hash, 1)) {
|
return 0; /* OK */
|
||||||
printf("Unable to msi_handle_dir()\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
}
|
||||||
/* Obtain a current signature from previously-signed file */
|
|
||||||
if ((ctx->options->cmd == CMD_SIGN && ctx->options->nest)
|
/*
|
||||||
|| (ctx->options->cmd == CMD_ATTACH && ctx->options->nest)
|
* Create a new PKCS#7 signature.
|
||||||
|| ctx->options->cmd == CMD_ADD) {
|
* [in, out] ctx: structure holds input and output data
|
||||||
MSI_ENTRY *dse = NULL;
|
* [out] hash: message digest BIO
|
||||||
MSI_ENTRY *ds = msi_signatures_get(ctx->msi_ctx->dirent, &dse);
|
* [returns] pointer to PKCS#7 structure
|
||||||
if (!ds) {
|
*/
|
||||||
printf("MSI file has no signature\n\n");
|
static PKCS7 *msi_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
return NULL; /* FAILED */
|
{
|
||||||
}
|
ASN1_OCTET_STRING *content;
|
||||||
if (!msi_check_MsiDigitalSignatureEx(ctx, dse)) {
|
PKCS7 *p7 = pkcs7_create(ctx);
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
len = GET_UINT32_LE(ds->size);
|
|
||||||
if (len == 0 || len >= MAXREGSECT) {
|
|
||||||
printf("Corrupted DigitalSignature stream length 0x%08X\n", len);
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
p = OPENSSL_malloc((size_t)len);
|
|
||||||
/* get current signature */
|
|
||||||
cursig = msi_pkcs7_get_digital_signature(ctx, ds, &p, len);
|
|
||||||
OPENSSL_free(p);
|
|
||||||
if (!cursig) {
|
|
||||||
printf("Unable to extract existing signature\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
if (ctx->options->cmd == CMD_ADD)
|
|
||||||
p7 = cursig;
|
|
||||||
}
|
|
||||||
if (ctx->options->cmd == CMD_ATTACH) {
|
|
||||||
/* Obtain an existing PKCS#7 signature */
|
|
||||||
p7 = pkcs7_get_sigfile(ctx);
|
|
||||||
if (!p7) {
|
|
||||||
printf("Unable to extract valid signature\n");
|
|
||||||
PKCS7_free(cursig);
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
} else if (ctx->options->cmd == CMD_SIGN) {
|
|
||||||
/* Create a new PKCS#7 signature */
|
|
||||||
p7 = pkcs7_create(ctx);
|
|
||||||
if (!p7) {
|
if (!p7) {
|
||||||
printf("Creating a new signature failed\n");
|
printf("Creating a new signature failed\n");
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!add_indirect_data_object(p7, hash, ctx)) {
|
if (!add_indirect_data_object(p7)) {
|
||||||
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
PKCS7_free(p7);
|
PKCS7_free(p7);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
if (!content) {
|
||||||
|
printf("Failed to get spcIndirectDataContent\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (ctx->options->nest)
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
ctx->options->prevsig = cursig;
|
printf("Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
return p7;
|
return p7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,34 +671,22 @@ static int msi_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
|||||||
* [out] outdata: outdata file BIO
|
* [out] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static BIO *msi_bio_free(BIO *hash, BIO *outdata)
|
static void msi_bio_free(BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
BIO_free_all(hash);
|
BIO_free_all(hash);
|
||||||
BIO_free_all(outdata);
|
BIO_free_all(outdata);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate a FILE_FORMAT_CTX structure and MSI format specific structures,
|
* Deallocate a FILE_FORMAT_CTX structure and MSI format specific structures,
|
||||||
* unmap indata file, unlink outfile.
|
* unmap indata file.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [out] outdata: outdata file BIO
|
* [out] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static void msi_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static void msi_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (outdata) {
|
|
||||||
BIO_free_all(hash);
|
|
||||||
BIO_free_all(outdata);
|
|
||||||
if (ctx->options->outfile) {
|
|
||||||
#ifdef WIN32
|
|
||||||
_unlink(ctx->options->outfile);
|
|
||||||
#else
|
|
||||||
unlink(ctx->options->outfile);
|
|
||||||
#endif /* WIN32 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unmap_file(ctx->options->indata, ctx->msi_ctx->fileend);
|
unmap_file(ctx->options->indata, ctx->msi_ctx->fileend);
|
||||||
msi_file_free(ctx->msi_ctx->msi);
|
msi_file_free(ctx->msi_ctx->msi);
|
||||||
msi_dirent_free(ctx->msi_ctx->dirent);
|
msi_dirent_free(ctx->msi_ctx->dirent);
|
||||||
@ -751,6 +695,11 @@ static void msi_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int msi_is_detaching_supported(void)
|
||||||
|
{
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MSI helper functions
|
* MSI helper functions
|
||||||
*/
|
*/
|
||||||
@ -791,18 +740,26 @@ static MSI_CTX *msi_ctx_get(char *indata, uint32_t filesize)
|
|||||||
return msi_ctx; /* OK */
|
return msi_ctx; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
static PKCS7 *msi_pkcs7_get_digital_signature(FILE_FORMAT_CTX *ctx, MSI_ENTRY *ds,
|
static PKCS7 *msi_pkcs7_get_digital_signature(FILE_FORMAT_CTX *ctx, MSI_ENTRY *ds)
|
||||||
char **p, uint32_t len)
|
|
||||||
{
|
{
|
||||||
PKCS7 *p7 = NULL;
|
PKCS7 *p7 = NULL;
|
||||||
const u_char *blob;
|
const u_char *blob;
|
||||||
|
char *p;
|
||||||
|
uint32_t len = GET_UINT32_LE(ds->size);
|
||||||
|
|
||||||
if (!msi_file_read(ctx->msi_ctx->msi, ds, 0, *p, len)) {
|
if (len == 0 || len >= MAXREGSECT) {
|
||||||
|
printf("Corrupted DigitalSignature stream length 0x%08X\n", len);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
p = OPENSSL_malloc((size_t)len);
|
||||||
|
if (!msi_file_read(ctx->msi_ctx->msi, ds, 0, p, len)) {
|
||||||
printf("DigitalSignature stream data error\n");
|
printf("DigitalSignature stream data error\n");
|
||||||
|
OPENSSL_free(p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
blob = (u_char *)*p;
|
blob = (u_char *)p;
|
||||||
p7 = d2i_PKCS7(NULL, &blob, len);
|
p7 = d2i_PKCS7(NULL, &blob, len);
|
||||||
|
OPENSSL_free(p);
|
||||||
if (!p7) {
|
if (!p7) {
|
||||||
printf("Failed to extract PKCS7 data\n");
|
printf("Failed to extract PKCS7 data\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1695,9 +1652,8 @@ static int stream_handle(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p_msi, uint3
|
|||||||
/* DigitalSignature or MsiDigitalSignatureEx: inlen == 0 */
|
/* DigitalSignature or MsiDigitalSignatureEx: inlen == 0 */
|
||||||
inlen = stream_read(msi, child->entry, p_msi, len_msi, p_msiex, len_msiex, &indata, inlen, is_root);
|
inlen = stream_read(msi, child->entry, p_msi, len_msi, p_msiex, len_msiex, &indata, inlen, is_root);
|
||||||
if (inlen == 0) {
|
if (inlen == 0) {
|
||||||
printf("Failed to read stream data\n");
|
|
||||||
OPENSSL_free(indata);
|
OPENSSL_free(indata);
|
||||||
continue;
|
continue; /* skip a null stream */
|
||||||
}
|
}
|
||||||
/* set the size of the user-defined data if this is a stream object */
|
/* set the size of the user-defined data if this is a stream object */
|
||||||
PUT_UINT32_LE(inlen, buf);
|
PUT_UINT32_LE(inlen, buf);
|
||||||
@ -2179,6 +2135,25 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a message digest value of a signed or unsigned MSI file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] calculated message digest BIO
|
||||||
|
*/
|
||||||
|
static BIO *msi_digest_calc_bio(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
if (ctx->options->add_msi_dse && !msi_calc_MsiDigitalSignatureEx(ctx, hash)) {
|
||||||
|
printf("Unable to calc MsiDigitalSignatureEx\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!msi_hash_dir(ctx->msi_ctx->msi, ctx->msi_ctx->dirent, hash, 1)) {
|
||||||
|
printf("Unable to msi_handle_dir()\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MsiDigitalSignatureEx is an enhanced signature type that
|
* MsiDigitalSignatureEx is an enhanced signature type that
|
||||||
* can be used when signing MSI files. In addition to
|
* can be used when signing MSI files. In addition to
|
||||||
@ -2188,7 +2163,7 @@ out:
|
|||||||
* The file content hashing part stays the same, so the
|
* The file content hashing part stays the same, so the
|
||||||
* msi_handle_dir() function can be used across both variants.
|
* msi_handle_dir() function can be used across both variants.
|
||||||
*
|
*
|
||||||
* When an MsiDigitalSigntaureEx section is present in an MSI file,
|
* When an MsiDigitalSignatureEx section is present in an MSI file,
|
||||||
* the meaning of the DigitalSignature section changes: Instead
|
* the meaning of the DigitalSignature section changes: Instead
|
||||||
* of being merely a file content hash (as what is output by the
|
* of being merely a file content hash (as what is output by the
|
||||||
* msi_handle_dir() function), it is now hashes both content
|
* msi_handle_dir() function), it is now hashes both content
|
||||||
@ -2236,6 +2211,11 @@ static int msi_calc_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, BIO *hash)
|
|||||||
printf("Unable to calculate MSI pre-hash ('metadata') hash\n");
|
printf("Unable to calculate MSI pre-hash ('metadata') hash\n");
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
|
if (ctx->msi_ctx->p_msiex) {
|
||||||
|
/* attach-signature counts MsiDigitalSignatureEx stream data twice */
|
||||||
|
OPENSSL_free(ctx->msi_ctx->p_msiex);
|
||||||
|
ctx->msi_ctx->p_msiex = NULL;
|
||||||
|
}
|
||||||
ctx->msi_ctx->p_msiex = OPENSSL_malloc(EVP_MAX_MD_SIZE);
|
ctx->msi_ctx->p_msiex = OPENSSL_malloc(EVP_MAX_MD_SIZE);
|
||||||
ctx->msi_ctx->len_msiex = (uint32_t)BIO_gets(prehash,
|
ctx->msi_ctx->len_msiex = (uint32_t)BIO_gets(prehash,
|
||||||
(char *)ctx->msi_ctx->p_msiex, EVP_MAX_MD_SIZE);
|
(char *)ctx->msi_ctx->p_msiex, EVP_MAX_MD_SIZE);
|
||||||
@ -2252,29 +2232,98 @@ static int msi_calc_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, BIO *hash)
|
|||||||
* section, we can't add a nested signature of a different MD type
|
* section, we can't add a nested signature of a different MD type
|
||||||
* without breaking the initial signature.
|
* without breaking the initial signature.
|
||||||
*/
|
*/
|
||||||
static int msi_check_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, MSI_ENTRY *dse)
|
static int msi_check_MsiDigitalSignatureEx(FILE_FORMAT_CTX *ctx, MSI_ENTRY *dse, PKCS7 *p7)
|
||||||
{
|
{
|
||||||
if (dse && GET_UINT32_LE(dse->size) != (uint32_t)EVP_MD_size(ctx->options->md)) {
|
if (dse && GET_UINT32_LE(dse->size) != (uint32_t)EVP_MD_size(ctx->options->md)) {
|
||||||
printf("Unable to add nested signature with a different MD type (-h parameter) "
|
X509_ALGOR *alg;
|
||||||
"than what exists in the MSI file already.\nThis is due to the presence of "
|
const ASN1_OBJECT *aoid;
|
||||||
"MsiDigitalSignatureEx (-add-msi-dse parameter).\n\n");
|
|
||||||
|
alg = sk_X509_ALGOR_value(p7->d.sign->md_algs, 0);
|
||||||
|
X509_ALGOR_get0(&aoid, NULL, NULL, alg);
|
||||||
|
printf("Message digest algorithm found : %s\n", OBJ_nid2sn(OBJ_obj2nid(aoid)));
|
||||||
|
printf("It is not possible to add a nested signature of a different MD type to the MSI file "
|
||||||
|
"without invalidating the initial signature, as the file contains MsiDigitalSignatureEx.\n"
|
||||||
|
"The file should be signed again, rather than adding a nested signature.\n");
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!dse && ctx->options->add_msi_dse) {
|
if (!dse && ctx->options->add_msi_dse) {
|
||||||
printf("Unable to add signature with -add-msi-dse parameter "
|
printf("It is not possible to add a nested signature using the -add-msi-dse parameter "
|
||||||
"without breaking the initial signature.\n\n");
|
"without invalidating the initial signature, as the file does not contain MsiDigitalSignatureEx.\n"
|
||||||
|
"The file should be signed again, rather than adding a nested signature.\n");
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (dse && !ctx->options->add_msi_dse) {
|
if (dse && !ctx->options->add_msi_dse) {
|
||||||
printf("Unable to add signature without -add-msi-dse parameter "
|
printf("It is not possible to add a signature without using the -add-msi-dse parameter, "
|
||||||
"without breaking the initial signature.\nThis is due to the presence of "
|
"as doing so would invalidate the initial signature due to the presence of MsiDigitalSignatureEx.\n"
|
||||||
"MsiDigitalSignatureEx (-add-msi-dse parameter).\n"
|
"In this case, consider using the -add-msi-dse option.\n");
|
||||||
"Should use -add-msi-dse options in this case.\n\n");
|
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
return 1; /* OK */
|
return 1; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] the size of the message digest when passed an EVP_MD structure (the size of the hash)
|
||||||
|
*/
|
||||||
|
static int msi_hash_length_get(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return EVP_MD_size(ctx->options->md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get DigitalSignature and MsiDigitalSignatureEx streams
|
||||||
|
* to check if the signature exists.
|
||||||
|
* [in, out] ctx: structure holds input and output datafv
|
||||||
|
* [returns] 0 on error or 1 on successs
|
||||||
|
*/
|
||||||
|
static int msi_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
char *indata = NULL;
|
||||||
|
uint32_t inlen;
|
||||||
|
MSI_ENTRY *ds, *dse = NULL;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
printf("Init error\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
ds = msi_signatures_get(ctx->msi_ctx->dirent, &dse);
|
||||||
|
if (!ds) {
|
||||||
|
printf("MSI file has no signature\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
inlen = GET_UINT32_LE(ds->size);
|
||||||
|
if (inlen == 0 || inlen >= MAXREGSECT) {
|
||||||
|
printf("Corrupted DigitalSignature stream length 0x%08X\n", inlen);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
indata = OPENSSL_malloc((size_t)inlen);
|
||||||
|
if (!msi_file_read(ctx->msi_ctx->msi, ds, 0, indata, inlen)) {
|
||||||
|
printf("DigitalSignature stream data error\n\n");
|
||||||
|
OPENSSL_free(indata);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!dse) {
|
||||||
|
printf("Warning: MsiDigitalSignatureEx stream doesn't exist\n");
|
||||||
|
} else {
|
||||||
|
ctx->msi_ctx->len_msiex = GET_UINT32_LE(dse->size);
|
||||||
|
if (ctx->msi_ctx->len_msiex == 0 || ctx->msi_ctx->len_msiex >= MAXREGSECT) {
|
||||||
|
printf("Corrupted MsiDigitalSignatureEx stream length 0x%08X\n",
|
||||||
|
ctx->msi_ctx->len_msiex);
|
||||||
|
OPENSSL_free(indata);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
ctx->msi_ctx->p_msiex = OPENSSL_malloc((size_t)ctx->msi_ctx->len_msiex);
|
||||||
|
if (!msi_file_read(ctx->msi_ctx->msi, dse, 0, (char *)ctx->msi_ctx->p_msiex,
|
||||||
|
ctx->msi_ctx->len_msiex)) {
|
||||||
|
printf("MsiDigitalSignatureEx stream data error\n\n");
|
||||||
|
OPENSSL_free(indata);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OPENSSL_free(indata);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
c-basic-offset: 4
|
c-basic-offset: 4
|
||||||
|
1288
osslsigncode.c
1288
osslsigncode.c
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@
|
|||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -73,20 +74,24 @@
|
|||||||
#endif /* SOCKET */
|
#endif /* SOCKET */
|
||||||
#endif /* __CYGWIN__ */
|
#endif /* __CYGWIN__ */
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#endif /* ENABLE_CURL */
|
||||||
|
|
||||||
#define MAX_TS_SERVERS 256
|
#define MAX_TS_SERVERS 256
|
||||||
#endif /* ENABLE_CURL */
|
|
||||||
|
|
||||||
#if defined (HAVE_TERMIOS_H) || defined (HAVE_GETPASS)
|
#if defined (HAVE_TERMIOS_H) || defined (HAVE_GETPASS)
|
||||||
#define PROVIDE_ASKPASS 1
|
#define PROVIDE_ASKPASS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
#define FILE_CREATE_MODE "w+b"
|
/* not WIN32, because strcasecmp exists in MinGW */
|
||||||
#else
|
#define strcasecmp _stricmp
|
||||||
#define FILE_CREATE_MODE "w+bx"
|
|
||||||
#endif
|
#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_UINT8_LE(p) ((const u_char *)(p))[0]
|
||||||
|
|
||||||
@ -175,6 +180,8 @@
|
|||||||
#define SPC_RFC3161_OBJID "1.3.6.1.4.1.311.3.3.1"
|
#define SPC_RFC3161_OBJID "1.3.6.1.4.1.311.3.3.1"
|
||||||
/* Microsoft OID Crypto 2.0 */
|
/* Microsoft OID Crypto 2.0 */
|
||||||
#define MS_CTL_OBJID "1.3.6.1.4.1.311.10.1"
|
#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 */
|
/* Microsoft OID Microsoft_Java */
|
||||||
#define MS_JAVA_SOMETHING "1.3.6.1.4.1.311.15.1"
|
#define MS_JAVA_SOMETHING "1.3.6.1.4.1.311.15.1"
|
||||||
|
|
||||||
@ -184,6 +191,7 @@
|
|||||||
#define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
|
#define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
|
||||||
#define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5"
|
#define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5"
|
||||||
#define PKCS9_COUNTER_SIGNATURE "1.2.840.113549.1.9.6"
|
#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 */
|
/* WIN_CERTIFICATE structure declared in Wintrust.h */
|
||||||
#define WIN_CERT_REVISION_2_0 0x0200
|
#define WIN_CERT_REVISION_2_0 0x0200
|
||||||
@ -218,6 +226,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
CMD_SIGN,
|
CMD_SIGN,
|
||||||
CMD_EXTRACT,
|
CMD_EXTRACT,
|
||||||
|
CMD_EXTRACT_DATA,
|
||||||
CMD_REMOVE,
|
CMD_REMOVE,
|
||||||
CMD_VERIFY,
|
CMD_VERIFY,
|
||||||
CMD_ADD,
|
CMD_ADD,
|
||||||
@ -252,17 +261,17 @@ typedef struct {
|
|||||||
const EVP_MD *md;
|
const EVP_MD *md;
|
||||||
char *url;
|
char *url;
|
||||||
time_t time;
|
time_t time;
|
||||||
#ifdef ENABLE_CURL
|
|
||||||
char *turl[MAX_TS_SERVERS];
|
char *turl[MAX_TS_SERVERS];
|
||||||
int nturl;
|
int nturl;
|
||||||
char *tsurl[MAX_TS_SERVERS];
|
char *tsurl[MAX_TS_SERVERS];
|
||||||
int ntsurl;
|
int ntsurl;
|
||||||
char *proxy;
|
char *proxy;
|
||||||
int noverifypeer;
|
int noverifypeer;
|
||||||
#endif /* ENABLE_CURL */
|
|
||||||
int addBlob;
|
int addBlob;
|
||||||
int nest;
|
int nest;
|
||||||
|
int index;
|
||||||
int ignore_timestamp;
|
int ignore_timestamp;
|
||||||
|
int ignore_cdp;
|
||||||
int verbose;
|
int verbose;
|
||||||
int add_msi_dse;
|
int add_msi_dse;
|
||||||
char *catalog;
|
char *catalog;
|
||||||
@ -282,10 +291,10 @@ typedef struct {
|
|||||||
STACK_OF(X509_CRL) *crls;
|
STACK_OF(X509_CRL) *crls;
|
||||||
cmd_type_t cmd;
|
cmd_type_t cmd;
|
||||||
char *indata;
|
char *indata;
|
||||||
PKCS7 *prevsig;
|
|
||||||
char *tsa_certfile;
|
char *tsa_certfile;
|
||||||
char *tsa_keyfile;
|
char *tsa_keyfile;
|
||||||
time_t tsa_time;
|
time_t tsa_time;
|
||||||
|
int nested_number;
|
||||||
} GLOBAL_OPTIONS;
|
} GLOBAL_OPTIONS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -326,6 +335,18 @@ typedef struct {
|
|||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(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 {
|
typedef struct {
|
||||||
ASN1_OBJECT *type;
|
ASN1_OBJECT *type;
|
||||||
ASN1_TYPE *value;
|
ASN1_TYPE *value;
|
||||||
@ -369,8 +390,6 @@ typedef struct {
|
|||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(MessageImprint)
|
DECLARE_ASN1_FUNCTIONS(MessageImprint)
|
||||||
|
|
||||||
#ifdef ENABLE_CURL
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ASN1_OBJECT *type;
|
ASN1_OBJECT *type;
|
||||||
ASN1_OCTET_STRING *signature;
|
ASN1_OCTET_STRING *signature;
|
||||||
@ -413,8 +432,6 @@ typedef struct {
|
|||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(TimeStampReq)
|
DECLARE_ASN1_FUNCTIONS(TimeStampReq)
|
||||||
|
|
||||||
#endif /* ENABLE_CURL */
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ASN1_INTEGER *seconds;
|
ASN1_INTEGER *seconds;
|
||||||
ASN1_INTEGER *millis;
|
ASN1_INTEGER *millis;
|
||||||
@ -462,6 +479,8 @@ typedef struct {
|
|||||||
DECLARE_ASN1_FUNCTIONS(MsCtlContent)
|
DECLARE_ASN1_FUNCTIONS(MsCtlContent)
|
||||||
|
|
||||||
typedef struct file_format_st FILE_FORMAT;
|
typedef struct file_format_st FILE_FORMAT;
|
||||||
|
|
||||||
|
typedef struct script_ctx_st SCRIPT_CTX;
|
||||||
typedef struct msi_ctx_st MSI_CTX;
|
typedef struct msi_ctx_st MSI_CTX;
|
||||||
typedef struct pe_ctx_st PE_CTX;
|
typedef struct pe_ctx_st PE_CTX;
|
||||||
typedef struct cab_ctx_st CAB_CTX;
|
typedef struct cab_ctx_st CAB_CTX;
|
||||||
@ -472,6 +491,7 @@ typedef struct {
|
|||||||
FILE_FORMAT *format;
|
FILE_FORMAT *format;
|
||||||
GLOBAL_OPTIONS *options;
|
GLOBAL_OPTIONS *options;
|
||||||
union {
|
union {
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
MSI_CTX *msi_ctx;
|
MSI_CTX *msi_ctx;
|
||||||
PE_CTX *pe_ctx;
|
PE_CTX *pe_ctx;
|
||||||
CAB_CTX *cab_ctx;
|
CAB_CTX *cab_ctx;
|
||||||
@ -480,6 +500,7 @@ typedef struct {
|
|||||||
};
|
};
|
||||||
} FILE_FORMAT_CTX;
|
} FILE_FORMAT_CTX;
|
||||||
|
|
||||||
|
extern FILE_FORMAT file_format_script;
|
||||||
extern FILE_FORMAT file_format_msi;
|
extern FILE_FORMAT file_format_msi;
|
||||||
extern FILE_FORMAT file_format_pe;
|
extern FILE_FORMAT file_format_pe;
|
||||||
extern FILE_FORMAT file_format_cab;
|
extern FILE_FORMAT file_format_cab;
|
||||||
@ -488,19 +509,23 @@ extern FILE_FORMAT file_format_appx;
|
|||||||
|
|
||||||
struct file_format_st {
|
struct file_format_st {
|
||||||
FILE_FORMAT_CTX *(*ctx_new) (GLOBAL_OPTIONS *option, BIO *hash, BIO *outdata);
|
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);
|
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);
|
int (*hash_length_get) (FILE_FORMAT_CTX *ctx);
|
||||||
int (*check_file) (FILE_FORMAT_CTX *ctx, int detached);
|
|
||||||
u_char *(*digest_calc) (FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
u_char *(*digest_calc) (FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
int (*verify_digests) (FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
int (*verify_digests) (FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
int (*verify_indirect_data) (FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj);
|
int (*verify_indirect_data) (FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj);
|
||||||
PKCS7 *(*pkcs7_extract) (FILE_FORMAT_CTX *ctx);
|
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 (*remove_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
PKCS7 *(*pkcs7_prepare) (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);
|
int (*append_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
void (*update_data_size) (FILE_FORMAT_CTX *data, BIO *outdata, PKCS7 *p7);
|
void (*update_data_size) (FILE_FORMAT_CTX *data, BIO *outdata, PKCS7 *p7);
|
||||||
BIO *(*bio_free) (BIO *hash, BIO *outdata);
|
void (*bio_free) (BIO *hash, BIO *outdata);
|
||||||
void (*ctx_cleanup) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
void (*ctx_cleanup) (FILE_FORMAT_CTX *ctx);
|
||||||
|
int (*is_detaching_supported) (void);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
377
pe.c
377
pe.c
@ -44,34 +44,40 @@ struct pe_ctx_st {
|
|||||||
/* FILE_FORMAT method prototypes */
|
/* FILE_FORMAT method prototypes */
|
||||||
static FILE_FORMAT_CTX *pe_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
static FILE_FORMAT_CTX *pe_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
static ASN1_OBJECT *pe_spc_image_data_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
static ASN1_OBJECT *pe_spc_image_data_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *pe_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
static int pe_hash_length_get(FILE_FORMAT_CTX *ctx);
|
static int pe_hash_length_get(FILE_FORMAT_CTX *ctx);
|
||||||
static int pe_check_file(FILE_FORMAT_CTX *ctx, int detached);
|
|
||||||
static u_char *pe_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
static u_char *pe_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
static int pe_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
static int pe_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
static int pe_verify_indirect_data(FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj);
|
static int pe_verify_indirect_data(FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj);
|
||||||
static PKCS7 *pe_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
static PKCS7 *pe_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *pe_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx);
|
||||||
static int pe_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int pe_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
static PKCS7 *pe_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int pe_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static PKCS7 *pe_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
static int pe_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
static int pe_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static void pe_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
static void pe_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
static BIO *pe_bio_free(BIO *hash, BIO *outdata);
|
static void pe_bio_free(BIO *hash, BIO *outdata);
|
||||||
static void pe_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static void pe_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pe_is_detaching_supported(void);
|
||||||
|
|
||||||
FILE_FORMAT file_format_pe = {
|
FILE_FORMAT file_format_pe = {
|
||||||
.ctx_new = pe_ctx_new,
|
.ctx_new = pe_ctx_new,
|
||||||
.data_blob_get = pe_spc_image_data_get,
|
.data_blob_get = pe_spc_image_data_get,
|
||||||
|
.pkcs7_contents_get = pe_pkcs7_contents_get,
|
||||||
.hash_length_get = pe_hash_length_get,
|
.hash_length_get = pe_hash_length_get,
|
||||||
.check_file = pe_check_file,
|
|
||||||
.digest_calc = pe_digest_calc,
|
.digest_calc = pe_digest_calc,
|
||||||
.verify_digests = pe_verify_digests,
|
.verify_digests = pe_verify_digests,
|
||||||
.verify_indirect_data = pe_verify_indirect_data,
|
.verify_indirect_data = pe_verify_indirect_data,
|
||||||
.pkcs7_extract = pe_pkcs7_extract,
|
.pkcs7_extract = pe_pkcs7_extract,
|
||||||
|
.pkcs7_extract_to_nest = pe_pkcs7_extract_to_nest,
|
||||||
.remove_pkcs7 = pe_remove_pkcs7,
|
.remove_pkcs7 = pe_remove_pkcs7,
|
||||||
.pkcs7_prepare = pe_pkcs7_prepare,
|
.process_data = pe_process_data,
|
||||||
|
.pkcs7_signature_new = pe_pkcs7_signature_new,
|
||||||
.append_pkcs7 = pe_append_pkcs7,
|
.append_pkcs7 = pe_append_pkcs7,
|
||||||
.update_data_size = pe_update_data_size,
|
.update_data_size = pe_update_data_size,
|
||||||
.bio_free = pe_bio_free,
|
.bio_free = pe_bio_free,
|
||||||
.ctx_cleanup = pe_ctx_cleanup
|
.ctx_cleanup = pe_ctx_cleanup,
|
||||||
|
.is_detaching_supported = pe_is_detaching_supported
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
@ -80,10 +86,12 @@ static PKCS7 *pe_pkcs7_get_file(char *indata, PE_CTX *pe_ctx);
|
|||||||
static uint32_t pe_calc_checksum(BIO *bio, uint32_t header_size);
|
static uint32_t pe_calc_checksum(BIO *bio, uint32_t header_size);
|
||||||
static uint32_t pe_calc_realchecksum(FILE_FORMAT_CTX *ctx);
|
static uint32_t pe_calc_realchecksum(FILE_FORMAT_CTX *ctx);
|
||||||
static int pe_modify_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
static int pe_modify_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static BIO *pe_digest_calc_bio(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
static int pe_page_hash_get(u_char **ph, int *phlen, int *phtype, SpcAttributeTypeAndOptionalValue *obj);
|
static int pe_page_hash_get(u_char **ph, int *phlen, int *phtype, SpcAttributeTypeAndOptionalValue *obj);
|
||||||
static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype);
|
static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype);
|
||||||
static int pe_verify_page_hash(FILE_FORMAT_CTX *ctx, u_char *ph, int phlen, int phtype);
|
static int pe_verify_page_hash(FILE_FORMAT_CTX *ctx, u_char *ph, int phlen, int phtype);
|
||||||
static SpcLink *pe_page_hash_link_get(FILE_FORMAT_CTX *ctx, int phtype);
|
static SpcLink *pe_page_hash_link_get(FILE_FORMAT_CTX *ctx, int phtype);
|
||||||
|
static int pe_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -112,12 +120,12 @@ static FILE_FORMAT_CTX *pe_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outd
|
|||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (memcmp(options->indata, "MZ", 2)) {
|
if (memcmp(options->indata, "MZ", 2)) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
pe_ctx = pe_ctx_get(options->indata, filesize);
|
pe_ctx = pe_ctx_get(options->indata, filesize);
|
||||||
if (!pe_ctx) {
|
if (!pe_ctx) {
|
||||||
unmap_file(options->infile, filesize);
|
unmap_file(options->indata, filesize);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
@ -170,6 +178,30 @@ static ASN1_OBJECT *pe_spc_image_data_get(u_char **p, int *plen, FILE_FORMAT_CTX
|
|||||||
return dtype; /* OK */
|
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 *pe_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 = pe_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);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
* [returns] the size of the message digest when passed an EVP_MD structure (the size of the hash)
|
* [returns] the size of the message digest when passed an EVP_MD structure (the size of the hash)
|
||||||
@ -180,121 +212,24 @@ static int pe_hash_length_get(FILE_FORMAT_CTX *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print current and calculated PE checksum,
|
* Returns a message digest value of a signed or unsigned PE file.
|
||||||
* check if the signature exists.
|
|
||||||
* [in, out] ctx: structure holds input and output data
|
|
||||||
* [in] detached: embedded/detached PKCS#7 signature switch
|
|
||||||
* [returns] 0 on error or 1 on success
|
|
||||||
*/
|
|
||||||
static int pe_check_file(FILE_FORMAT_CTX *ctx, int detached)
|
|
||||||
{
|
|
||||||
uint32_t real_pe_checksum, sum = 0;
|
|
||||||
|
|
||||||
if (!ctx) {
|
|
||||||
printf("Init error\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
real_pe_checksum = pe_calc_realchecksum(ctx);
|
|
||||||
if (ctx->pe_ctx->pe_checksum == real_pe_checksum) {
|
|
||||||
printf("PE checksum : %08X\n\n", real_pe_checksum);
|
|
||||||
} else {
|
|
||||||
printf("Current PE checksum : %08X\n", ctx->pe_ctx->pe_checksum);
|
|
||||||
printf("Calculated PE checksum: %08X\n", real_pe_checksum);
|
|
||||||
printf("Warning: invalid PE checksum\n\n");
|
|
||||||
}
|
|
||||||
if (detached) {
|
|
||||||
printf("Checking the specified catalog file\n\n");
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
|
||||||
if (ctx->pe_ctx->sigpos == 0 || ctx->pe_ctx->siglen == 0
|
|
||||||
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend) {
|
|
||||||
printf("No signature found\n\n");
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If the sum of the rounded dwLength values does not equal the Size value,
|
|
||||||
* then either the attribute certificate table or the Size field is corrupted.
|
|
||||||
*/
|
|
||||||
while (sum < ctx->pe_ctx->siglen) {
|
|
||||||
uint32_t len = GET_UINT32_LE(ctx->options->indata + ctx->pe_ctx->sigpos + sum);
|
|
||||||
if (ctx->pe_ctx->siglen - len > 8) {
|
|
||||||
printf("Corrupted attribute certificate table\n");
|
|
||||||
printf("Attribute certificate table size : %08X\n", ctx->pe_ctx->siglen);
|
|
||||||
printf("Attribute certificate entry length: %08X\n\n", len);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
/* quadword align data */
|
|
||||||
len += len % 8 ? 8 - len % 8 : 0;
|
|
||||||
sum += len;
|
|
||||||
}
|
|
||||||
if (sum != ctx->pe_ctx->siglen) {
|
|
||||||
printf("Corrupted attribute certificate table\n");
|
|
||||||
printf("Attribute certificate table size : %08X\n", ctx->pe_ctx->siglen);
|
|
||||||
printf("Sum of the rounded dwLength values: %08X\n\n", sum);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
return 1; /* OK */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute a message digest value of a signed or unsigned PE file.
|
|
||||||
* [in] ctx: structure holds input and output data
|
* [in] ctx: structure holds input and output data
|
||||||
* [in] md: message digest algorithm
|
* [in] md: message digest algorithm
|
||||||
* [returns] pointer to calculated message digest
|
* [returns] pointer to calculated message digest
|
||||||
*/
|
*/
|
||||||
static u_char *pe_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
static u_char *pe_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
||||||
{
|
{
|
||||||
size_t written;
|
u_char *mdbuf;
|
||||||
uint32_t idx = 0, fileend;
|
BIO *bhash = pe_digest_calc_bio(ctx, md);
|
||||||
u_char *mdbuf = NULL;
|
if (!bhash) {
|
||||||
BIO *bhash = BIO_new(BIO_f_md());
|
|
||||||
|
|
||||||
if (!BIO_set_md(bhash, md)) {
|
|
||||||
printf("Unable to set the message digest of BIO\n");
|
|
||||||
BIO_free_all(bhash);
|
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
BIO_push(bhash, BIO_new(BIO_s_null()));
|
|
||||||
if (ctx->pe_ctx->sigpos)
|
|
||||||
fileend = ctx->pe_ctx->sigpos;
|
|
||||||
else
|
|
||||||
fileend = ctx->pe_ctx->fileend;
|
|
||||||
|
|
||||||
/* ctx->pe_ctx->header_size + 88 + 4 + 60 + ctx->pe_ctx->pe32plus * 16 + 8 */
|
|
||||||
if (!BIO_write_ex(bhash, ctx->options->indata, ctx->pe_ctx->header_size + 88, &written)
|
|
||||||
|| written != ctx->pe_ctx->header_size + 88) {
|
|
||||||
BIO_free_all(bhash);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
idx += (uint32_t)written + 4;
|
|
||||||
if (!BIO_write_ex(bhash, ctx->options->indata + idx,
|
|
||||||
60 + ctx->pe_ctx->pe32plus * 16, &written)
|
|
||||||
|| written != 60 + ctx->pe_ctx->pe32plus * 16) {
|
|
||||||
BIO_free_all(bhash);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
idx += (uint32_t)written + 8;
|
|
||||||
if (!bio_hash_data(bhash, ctx->options->indata, idx, fileend)) {
|
|
||||||
printf("Unable to calculate digest\n");
|
|
||||||
BIO_free_all(bhash);
|
|
||||||
return 0; /* FAILED */
|
|
||||||
}
|
|
||||||
if (!ctx->pe_ctx->sigpos) {
|
|
||||||
/* pad (with 0's) unsigned PE file to 8 byte boundary */
|
|
||||||
int len = 8 - ctx->pe_ctx->fileend % 8;
|
|
||||||
if (len > 0 && len != 8) {
|
|
||||||
char *buf = OPENSSL_malloc(8);
|
|
||||||
memset(buf, 0, (size_t)len);
|
|
||||||
BIO_write(bhash, buf, len);
|
|
||||||
OPENSSL_free(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mdbuf = OPENSSL_malloc((size_t)EVP_MD_size(md));
|
mdbuf = OPENSSL_malloc((size_t)EVP_MD_size(md));
|
||||||
BIO_gets(bhash, (char*)mdbuf, EVP_MD_size(md));
|
BIO_gets(bhash, (char*)mdbuf, EVP_MD_size(md));
|
||||||
BIO_free_all(bhash);
|
BIO_free_all(bhash);
|
||||||
return mdbuf; /* OK */
|
return mdbuf; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate message digest and page_hash and compare to values retrieved
|
* Calculate message digest and page_hash and compare to values retrieved
|
||||||
* from PKCS#7 signedData.
|
* from PKCS#7 signedData.
|
||||||
@ -387,13 +322,22 @@ static int pe_verify_indirect_data(FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOpti
|
|||||||
*/
|
*/
|
||||||
static PKCS7 *pe_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
static PKCS7 *pe_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->pe_ctx->sigpos == 0 || ctx->pe_ctx->siglen == 0
|
if (!pe_check_file(ctx)) {
|
||||||
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend) {
|
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
return pe_pkcs7_get_file(ctx->options->indata, ctx->pe_ctx);
|
return pe_pkcs7_get_file(ctx->options->indata, ctx->pe_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *pe_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return pe_pkcs7_extract(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove existing signature.
|
* Remove existing signature.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
@ -403,9 +347,8 @@ static PKCS7 *pe_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
|||||||
*/
|
*/
|
||||||
static int pe_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int pe_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
if (ctx->pe_ctx->sigpos == 0) {
|
if (!pe_check_file(ctx)) {
|
||||||
printf("PE file does not have any signature\n");
|
return 1; /* FAILED, no signature */
|
||||||
return 1; /* FAILED */
|
|
||||||
}
|
}
|
||||||
/* Strip current signature */
|
/* Strip current signature */
|
||||||
ctx->pe_ctx->fileend = ctx->pe_ctx->sigpos;
|
ctx->pe_ctx->fileend = ctx->pe_ctx->sigpos;
|
||||||
@ -417,59 +360,57 @@ static int pe_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Obtain an existing signature or create a new one.
|
* Modify specific type data and calculate a hash (message digest) of data.
|
||||||
* [in, out] ctx: structure holds input and output data
|
* [in, out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [out] outdata: outdata file BIO
|
* [out] outdata: outdata file BIO
|
||||||
* [returns] pointer to PKCS#7 structure
|
* [returns] 1 on error or 0 on success
|
||||||
*/
|
*/
|
||||||
static PKCS7 *pe_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static int pe_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
PKCS7 *cursig = NULL, *p7 = NULL;
|
|
||||||
|
|
||||||
/* Obtain a current signature from previously-signed file */
|
|
||||||
if ((ctx->options->cmd == CMD_SIGN && ctx->options->nest)
|
|
||||||
|| (ctx->options->cmd == CMD_ATTACH && ctx->options->nest)
|
|
||||||
|| ctx->options->cmd == CMD_ADD) {
|
|
||||||
cursig = pe_pkcs7_get_file(ctx->options->indata, ctx->pe_ctx);
|
|
||||||
if (!cursig) {
|
|
||||||
printf("Unable to extract existing signature\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
|
||||||
if (ctx->options->cmd == CMD_ADD)
|
|
||||||
p7 = cursig;
|
|
||||||
}
|
|
||||||
if (ctx->pe_ctx->sigpos > 0) {
|
if (ctx->pe_ctx->sigpos > 0) {
|
||||||
/* Strip current signature */
|
/* Strip current signature */
|
||||||
ctx->pe_ctx->fileend = ctx->pe_ctx->sigpos;
|
ctx->pe_ctx->fileend = ctx->pe_ctx->sigpos;
|
||||||
}
|
}
|
||||||
if (!pe_modify_header(ctx, hash, outdata)) {
|
if (!pe_modify_header(ctx, hash, outdata)) {
|
||||||
printf("Unable to modify file header\n");
|
printf("Unable to modify file header\n");
|
||||||
return NULL; /* FAILED */
|
return 1; /* FAILED */
|
||||||
}
|
}
|
||||||
if (ctx->options->cmd == CMD_ATTACH) {
|
return 0; /* OK */
|
||||||
/* Obtain an existing PKCS#7 signature */
|
|
||||||
p7 = pkcs7_get_sigfile(ctx);
|
|
||||||
if (!p7) {
|
|
||||||
printf("Unable to extract valid signature\n");
|
|
||||||
PKCS7_free(cursig);
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
}
|
||||||
} else if (ctx->options->cmd == CMD_SIGN) {
|
|
||||||
/* Create a new PKCS#7 signature */
|
/*
|
||||||
p7 = pkcs7_create(ctx);
|
* 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 *pe_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
PKCS7 *p7 = pkcs7_create(ctx);
|
||||||
|
|
||||||
if (!p7) {
|
if (!p7) {
|
||||||
printf("Creating a new signature failed\n");
|
printf("Creating a new signature failed\n");
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!add_indirect_data_object(p7, hash, ctx)) {
|
if (!add_indirect_data_object(p7)) {
|
||||||
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
PKCS7_free(p7);
|
PKCS7_free(p7);
|
||||||
return NULL; /* FAILED */
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
if (!content) {
|
||||||
|
printf("Failed to get spcIndirectDataContent\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
}
|
}
|
||||||
if (ctx->options->nest)
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
ctx->options->prevsig = cursig;
|
printf("Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
return p7;
|
return p7;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,40 +496,33 @@ static void pe_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
|||||||
* [out] outdata: outdata file BIO (unused)
|
* [out] outdata: outdata file BIO (unused)
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static BIO *pe_bio_free(BIO *hash, BIO *outdata)
|
static void pe_bio_free(BIO *hash, BIO *outdata)
|
||||||
{
|
{
|
||||||
/* squash the unused parameter warning */
|
/* squash the unused parameter warning */
|
||||||
(void)outdata;
|
(void)outdata;
|
||||||
|
|
||||||
BIO_free_all(hash);
|
BIO_free_all(hash);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocate a FILE_FORMAT_CTX structure and PE format specific structure,
|
* Deallocate a FILE_FORMAT_CTX structure and PE format specific structure,
|
||||||
* unmap indata file, unlink outfile.
|
* unmap indata file.
|
||||||
* [out] ctx: structure holds input and output data
|
* [out] ctx: structure holds input and output data
|
||||||
* [out] hash: message digest BIO
|
* [out] hash: message digest BIO
|
||||||
* [in] outdata: outdata file BIO
|
* [in] outdata: outdata file BIO
|
||||||
* [returns] none
|
* [returns] none
|
||||||
*/
|
*/
|
||||||
static void pe_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
static void pe_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (outdata) {
|
|
||||||
BIO_free_all(hash);
|
|
||||||
if (ctx->options->outfile) {
|
|
||||||
#ifdef WIN32
|
|
||||||
_unlink(ctx->options->outfile);
|
|
||||||
#else
|
|
||||||
unlink(ctx->options->outfile);
|
|
||||||
#endif /* WIN32 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unmap_file(ctx->options->indata, ctx->pe_ctx->fileend);
|
unmap_file(ctx->options->indata, ctx->pe_ctx->fileend);
|
||||||
OPENSSL_free(ctx->pe_ctx);
|
OPENSSL_free(ctx->pe_ctx);
|
||||||
OPENSSL_free(ctx);
|
OPENSSL_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pe_is_detaching_supported(void)
|
||||||
|
{
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PE helper functions
|
* PE helper functions
|
||||||
*/
|
*/
|
||||||
@ -653,14 +587,11 @@ static PE_CTX *pe_ctx_get(char *indata, uint32_t filesize)
|
|||||||
siglen = GET_UINT32_LE(indata + header_size + 152 + pe32plus * 16 + 4);
|
siglen = GET_UINT32_LE(indata + header_size + 152 + pe32plus * 16 + 4);
|
||||||
/* Since fix for MS Bulletin MS12-024 we can really assume
|
/* Since fix for MS Bulletin MS12-024 we can really assume
|
||||||
that signature should be last part of file */
|
that signature should be last part of file */
|
||||||
if ((sigpos > 0 && sigpos < filesize && sigpos + siglen != filesize)
|
if ((sigpos != 0 || siglen != 0) &&
|
||||||
|| (sigpos >= filesize)) {
|
(sigpos == 0 || siglen == 0 || sigpos >= filesize || sigpos + siglen != filesize)) {
|
||||||
printf("Corrupt PE file - current signature not at the end of the file\n");
|
printf("Ignoring PE signature not at the end of the file\n");
|
||||||
return NULL; /* FAILED */
|
sigpos = 0;
|
||||||
}
|
siglen = 0;
|
||||||
if ((sigpos > 0 && siglen == 0) || (sigpos == 0 && siglen > 0)) {
|
|
||||||
printf("Corrupt signature\n");
|
|
||||||
return NULL; /* FAILED */
|
|
||||||
}
|
}
|
||||||
pe_ctx = OPENSSL_zalloc(sizeof(PE_CTX));
|
pe_ctx = OPENSSL_zalloc(sizeof(PE_CTX));
|
||||||
pe_ctx->header_size = header_size;
|
pe_ctx->header_size = header_size;
|
||||||
@ -836,6 +767,62 @@ static int pe_modify_header(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
|||||||
return 1; /* OK */
|
return 1; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a message digest value of a signed or unsigned PE file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] calculated message digest BIO
|
||||||
|
*/
|
||||||
|
static BIO *pe_digest_calc_bio(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
size_t written;
|
||||||
|
uint32_t idx = 0, fileend;
|
||||||
|
BIO *bhash = BIO_new(BIO_f_md());
|
||||||
|
|
||||||
|
if (!BIO_set_md(bhash, md)) {
|
||||||
|
printf("Unable to set the message digest of BIO\n");
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_push(bhash, BIO_new(BIO_s_null()));
|
||||||
|
if (ctx->pe_ctx->sigpos)
|
||||||
|
fileend = ctx->pe_ctx->sigpos;
|
||||||
|
else
|
||||||
|
fileend = ctx->pe_ctx->fileend;
|
||||||
|
|
||||||
|
/* ctx->pe_ctx->header_size + 88 + 4 + 60 + ctx->pe_ctx->pe32plus * 16 + 8 */
|
||||||
|
if (!BIO_write_ex(bhash, ctx->options->indata, ctx->pe_ctx->header_size + 88, &written)
|
||||||
|
|| written != ctx->pe_ctx->header_size + 88) {
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
idx += (uint32_t)written + 4;
|
||||||
|
if (!BIO_write_ex(bhash, ctx->options->indata + idx,
|
||||||
|
60 + ctx->pe_ctx->pe32plus * 16, &written)
|
||||||
|
|| written != 60 + ctx->pe_ctx->pe32plus * 16) {
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
idx += (uint32_t)written + 8;
|
||||||
|
if (!bio_hash_data(bhash, ctx->options->indata, idx, fileend)) {
|
||||||
|
printf("Unable to calculate digest\n");
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!ctx->pe_ctx->sigpos) {
|
||||||
|
/* pad (with 0's) unsigned PE file to 8 byte boundary */
|
||||||
|
int len = 8 - ctx->pe_ctx->fileend % 8;
|
||||||
|
if (len > 0 && len != 8) {
|
||||||
|
char *buf = OPENSSL_malloc(8);
|
||||||
|
memset(buf, 0, (size_t)len);
|
||||||
|
BIO_write(bhash, buf, len);
|
||||||
|
OPENSSL_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bhash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Page hash support
|
* Page hash support
|
||||||
*/
|
*/
|
||||||
@ -1172,6 +1159,58 @@ static SpcLink *pe_page_hash_link_get(FILE_FORMAT_CTX *ctx, int phtype)
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print current and calculated PE checksum,
|
||||||
|
* check if the signature exists.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pe_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
uint32_t real_pe_checksum, sum = 0;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
printf("Init error\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
real_pe_checksum = pe_calc_realchecksum(ctx);
|
||||||
|
if (ctx->pe_ctx->pe_checksum == real_pe_checksum) {
|
||||||
|
printf("PE checksum : %08X\n\n", real_pe_checksum);
|
||||||
|
} else {
|
||||||
|
printf("Current PE checksum : %08X\n", ctx->pe_ctx->pe_checksum);
|
||||||
|
printf("Calculated PE checksum: %08X\n", real_pe_checksum);
|
||||||
|
printf("Warning: invalid PE checksum\n\n");
|
||||||
|
}
|
||||||
|
if (ctx->pe_ctx->sigpos == 0 || ctx->pe_ctx->siglen == 0
|
||||||
|
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend) {
|
||||||
|
printf("No signature found\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If the sum of the rounded dwLength values does not equal the Size value,
|
||||||
|
* then either the attribute certificate table or the Size field is corrupted.
|
||||||
|
*/
|
||||||
|
while (sum < ctx->pe_ctx->siglen) {
|
||||||
|
uint32_t len = GET_UINT32_LE(ctx->options->indata + ctx->pe_ctx->sigpos + sum);
|
||||||
|
if (ctx->pe_ctx->siglen - len > 8) {
|
||||||
|
printf("Corrupted attribute certificate table\n");
|
||||||
|
printf("Attribute certificate table size : %08X\n", ctx->pe_ctx->siglen);
|
||||||
|
printf("Attribute certificate entry length: %08X\n\n", len);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
/* quadword align data */
|
||||||
|
len += len % 8 ? 8 - len % 8 : 0;
|
||||||
|
sum += len;
|
||||||
|
}
|
||||||
|
if (sum != ctx->pe_ctx->siglen) {
|
||||||
|
printf("Corrupted attribute certificate table\n");
|
||||||
|
printf("Attribute certificate table size : %08X\n", ctx->pe_ctx->siglen);
|
||||||
|
printf("Sum of the rounded dwLength values: %08X\n\n", sum);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
c-basic-offset: 4
|
c-basic-offset: 4
|
||||||
|
891
script.c
Normal file
891
script.c
Normal file
@ -0,0 +1,891 @@
|
|||||||
|
/*
|
||||||
|
* 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)) {
|
||||||
|
printf("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) {
|
||||||
|
printf("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)) {
|
||||||
|
printf("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, der_max_length, der_length;
|
||||||
|
char *ptr;
|
||||||
|
BIO *bio_mem, *bio_b64 = NULL;
|
||||||
|
char *base64_data = NULL;
|
||||||
|
char *der_data = NULL;
|
||||||
|
const char *der_tmp;
|
||||||
|
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) {
|
||||||
|
printf("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) {
|
||||||
|
printf("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) {
|
||||||
|
printf("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);
|
||||||
|
|
||||||
|
/* allocate memory for DER output */
|
||||||
|
der_max_length = BIO_ctrl_pending(bio_b64);
|
||||||
|
der_data = OPENSSL_malloc(der_max_length);
|
||||||
|
if (!der_data)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* decode Base64 to DER */
|
||||||
|
if (!BIO_read_ex(bio_b64, der_data, der_max_length, &der_length))
|
||||||
|
goto cleanup;
|
||||||
|
if (der_length <= 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* decode DER */
|
||||||
|
der_tmp = der_data;
|
||||||
|
retval = d2i_PKCS7(NULL, (const unsigned char **)&der_tmp, (int)der_length);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
OPENSSL_free(base64_data);
|
||||||
|
OPENSSL_free(clean_base64);
|
||||||
|
OPENSSL_free(der_data);
|
||||||
|
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 1; /* FAILED */
|
||||||
|
if (!script_digest_convert(hash, ctx, ctx->script_ctx->fileend))
|
||||||
|
return 1; /* FAILED */
|
||||||
|
return 0; /* 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) {
|
||||||
|
printf("Creating a new signature failed\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!add_indirect_data_object(p7)) {
|
||||||
|
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
if (!content) {
|
||||||
|
printf("Failed to get spcIndirectDataContent\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
|
printf("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)) {
|
||||||
|
printf("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)) {
|
||||||
|
printf("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) {
|
||||||
|
printf("Init error\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->script_ctx->sigpos == 0
|
||||||
|
|| ctx->script_ctx->sigpos > ctx->script_ctx->fileend) {
|
||||||
|
printf("No signature found\n\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:
|
||||||
|
*/
|
@ -1,22 +1,22 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDoTCCAomgAwIBAgIUfuEVHNA/1VLDJI9mhANrBndIj6swDQYJKoZIhvcNAQEL
|
MIIDoTCCAomgAwIBAgIUVD6Q+gnrOmJWbEnmfydpUg2JNmswDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTcwMTAxMDAwMDAwWhcNMjYxMTEwMDAwMDAwWjBYMQswCQYDVQQGEwJQTDEVMBMG
|
MTcwMTAxMDAwMDAwWhcNMzYxMjI3MDAwMDAwWjBYMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEQMA4GA1UEAwwHUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
cml0eTEQMA4GA1UEAwwHUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||||
AQoCggEBAMRykK9mZCSpkVUbCq1r12OXvIDkcjj+g4JpyZOrmPpz5RvmLvYBBgeV
|
AQoCggEBAMUvCAWI9LrgtVw9RARZLFb/qB1868H86eyr8oITzXl6u9FSQwvGH1MG
|
||||||
IsUcqHm3/uSLpOFu/pwFJ2CBZVPJ1d49Y9DVnNR1dUbneWX9tE7A6NV9IG1kVagM
|
szRhuD9TJAjy1uIiVPJ7ez2VjKXm2G9lUZMPJQRt50XTGbsGGDi4ITU1W3P+HI5u
|
||||||
veI/ANLuRi0H51aAZS9L8c6WxlR4+pxJoCZp1tyTGmfjxzBEXUWvyUrIMrW/r9TH
|
45I0IL14Qv/R8X26lndBzlY4ImoCTAN4KzdfvoGLaMpNvbC1P7a4mlukrumi3WKT
|
||||||
u5gGgR6k86EbH7q71XRLhLeEi9QGCG24gobngYNZa5mb8DgLCkUeFtRsrYGEUT0G
|
RAq46Mj5DAqr63NOolWimtTB+h0ZWv+xxngR7cfo+EimvhPB7y3xhY9OJ/27l6mJ
|
||||||
HTpAGXUrpAb3U7+4LkGaS6mc0NPTW4lz06Z3VhyYwwAbgU2DZQjMpqYWv6UctOP+
|
uQJohz5PmzhZByluMhicTsd2cJEKQb7jnih492okCj6vH/FJmKg+DzXKTyue5Ki4
|
||||||
5elPDc/PrTAdHAgbOhgvt1HUlqgn7lUCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB
|
2jhzM9v1npyIkd7s/gnZVEsHH6oQIt8CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB
|
||||||
/zAdBgNVHQ4EFgQUWIpzlJI+vefcJwcNGHwwRms/2ncwHwYDVR0jBBgwFoAUWIpz
|
/zAdBgNVHQ4EFgQUGjxG/vql0oJgItr7HsLaW+koiMgwHwYDVR0jBBgwFoAUGjxG
|
||||||
lJI+vefcJwcNGHwwRms/2ncwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUA
|
/vql0oJgItr7HsLaW+koiMgwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUA
|
||||||
A4IBAQAl+G1nXXW5u3notmAG5y8kwufFqNi5Jn1HVbT08w4IiteWMw3D9GEOCueM
|
A4IBAQAy7AKbO8B8Njseqjy2LAj2sKHCLc1jsQa7izOAtr852NYFAfpBvkqQfxne
|
||||||
g5A03bC/Xv1PRvMatXQSARRvvVl3y1l98sA+97SP/FFUla3W5Rn91OsWd4qkcXhv
|
8k5iPKmcJE+Sm4wv3V/lzx2AHEXAPa7BgiAo7yeo9UbrDgRRGw4MirQ/djp44ekv
|
||||||
CtPKHpz0SCjKLv3HG/C7fBJPG9XHMgkGZarM2KsQUlkn7DjdBccYcp/zJvtvm+be
|
KCc54bSE/paUZyEWKr8NbdBy7SZfZ/Dd+XUY2lbm3Mue3AzWl4xp4StoT6oaw6VI
|
||||||
nR5ZqE6LI52WCXg0w/KlJlildU5LE/bvHbfmRUVm/4GhUNN8ko8eG67ueuftkeTD
|
H6bIhZupond/RWp4jmHHEfvl4T6YLzl5FC+Ec2xBbpk5vAVZgyfrlv+W6V/il/X9
|
||||||
banKmnuSay02I42A0th2w8Hz7oaOUEpl8S9TfqeFuqLhtUP0FzUNMPAg0o5YTpe4
|
KTZl5ax4FJAm7vPn6fsgdAM5y24zJUAkeakKFsBYtoVoGg1iiFuMEGwFRn7EZYl1
|
||||||
xAArbPbFvH2l3plEaYccKYvbAGT/
|
8D16qEH+YPLCzujH1PhzjmmAfKl2
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
Binary file not shown.
@ -2,12 +2,12 @@
|
|||||||
MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJQTDEVMBMGA1UE
|
MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJQTDEVMBMGA1UE
|
||||||
CgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
|
CgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
|
||||||
eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBFw0xOTAxMDEwMDAwMDBaFw00MzAx
|
eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBFw0xOTAxMDEwMDAwMDBaFw00MzAx
|
||||||
MDEwMDAwMDBaMCcwJQIUSXAaPeUatfheDTFo77LnMBHgyeMXDTIzMDQyODEyMzMz
|
MDEwMDAwMDBaMCcwJQIUazbrVgbYb+IN803UmJJa0DPHQsAXDTI0MDIyNzE1MzAx
|
||||||
OVqgMDAuMB8GA1UdIwQYMBaAFOP6v42ECbVR/AiLDZ7f2WKtYXILMAsGA1UdFAQE
|
NFqgMDAuMB8GA1UdIwQYMBaAFGQQ8as5N9zB/bsdyD9BWHdiJ+8pMAsGA1UdFAQE
|
||||||
AgIQATANBgkqhkiG9w0BAQsFAAOCAQEARMWBcG6sanX3nwoSPGcUNEkYG2+qB8/w
|
AgIQATANBgkqhkiG9w0BAQsFAAOCAQEAV+Ce8WaNN/PXbVT9rOy/TS2EDrM/oFPG
|
||||||
wlcWWY7RfOGQWVHqbVvklJdTYFDw+mA6RuATMOd5S6hXa8tms4L2YQUmYyfNOyJu
|
vwZr2IQDcBtgFV5DpNZRKJo2m4mjPPt1eCjE404U2r6081bvq3PtwSPwezV+uCzF
|
||||||
+INPDnqueQshFZ8PqBTaP6O/NRI/LOLpcIIohgemwfPYPrbd/JqcLlQ2Vbgb9Lnb
|
dDUafeR0eZhmzxD8M2Jmi5hGp3fQevDrA4+RR33DneYSNfzGx35VN8v/L7/TuA5X
|
||||||
CYZWGOF7AKC0ugTTvLuWr9LPwmWFdORtmm3UJfFOPDX6zmHPAPhBUuyrxl8UoNZB
|
0PG8b5hL9f3vsVXvFRj6hMkRy5m+gxFfWW/Uw3fXIt9sDLJ+eAKURdqn1c3CEwD6
|
||||||
ZPvgeBjbyQy3MaJsbaniwoOahmT+MbYV/0/YRwI5XDxjiOdJSBz3Wd5YDNDozvG6
|
bzh0s6dSXT4wp5/l96x8fKAv5hMqDC7KufvwjhhSXdYXDOHDQcv0g5aLo8Ug8dHg
|
||||||
zZMHtF9TkUZjmLUe3Jm0GnS33gU8SB6YdYpnnPg+Up4w5sye90pk9A==
|
NJHqbTAAViyGfvsS9/pYb8kHpAWvaADK84tzaMzj7uCDXlCZEjIr7w==
|
||||||
-----END X509 CRL-----
|
-----END X509 CRL-----
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
MIICMzCCARsCAQEwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UEBhMCUEwxFTATBgNV
|
MIICMzCCARsCAQEwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UEBhMCUEwxFTATBgNV
|
||||||
BAoMDG9zc2xzaWduY29kZTEgMB4GA1UECwwXQ2VydGlmaWNhdGlvbiBBdXRob3Jp
|
BAoMDG9zc2xzaWduY29kZTEgMB4GA1UECwwXQ2VydGlmaWNhdGlvbiBBdXRob3Jp
|
||||||
dHkxHzAdBgNVBAMMFkludGVybWVkaWF0ZSBDQSBDUkwgRFAXDTE5MDEwMTAwMDAw
|
dHkxHzAdBgNVBAMMFkludGVybWVkaWF0ZSBDQSBDUkwgRFAXDTE5MDEwMTAwMDAw
|
||||||
MFoXDTQzMDEwMTAwMDAwMFowTjAlAhQxdzwUXgMSEn/RzOwbdKtxlLgYJhcNMjMw
|
MFoXDTQzMDEwMTAwMDAwMFowTjAlAhQcZvYIe2b1FreAKfoi/uGkSGJCthcNMjQw
|
||||||
NDI4MTIzMzQwWjAlAhRJcBo95Rq1+F4NMWjvsucwEeDJ4xcNMjMwNDI4MTIzMzM5
|
MjI3MTUzMDE0WjAlAhRrNutWBthv4g3zTdSYklrQM8dCwBcNMjQwMjI3MTUzMDE0
|
||||||
WqAwMC4wHwYDVR0jBBgwFoAUYbtAOknHjmiu3l8ONAUY387kFi8wCwYDVR0UBAQC
|
WqAwMC4wHwYDVR0jBBgwFoAUFDxiqeJxiJbmZ4erKH0pBIhq7SMwCwYDVR0UBAQC
|
||||||
AhACMA0GCSqGSIb3DQEBCwUAA4IBAQBOPbjiBQ1jOEjfQ1Q3/DBfzFKxeL7Cdoiq
|
AhACMA0GCSqGSIb3DQEBCwUAA4IBAQBZzGXEP4XdKuJ8ANIBGPu1Z+7T+4ln+nu3
|
||||||
6l1psqamZRTmU0a+1qRH/qokB0gA1XeeYIZRcruthHDk87F+WZPCKIr5cqfH2RFA
|
MEPC9BexVAA02YPZx6i4c3cHC87aOL7zsr/K9OeF5MAYzi2QJwsenF4b9QL2rzQV
|
||||||
xjDEkwgA8OZSdSMh+ZhBLBoGjZhFdnX/FknMcA23cLnzuv4RmsbiokwWrysebDNY
|
sCAb3sY5ImAxN38GTJ+oI+uTeOefNE0wS7pP4phRmYNZwyDhxA2iT76+luoygyth
|
||||||
DbTQpa/OFvqmHmgXbhrBqUinF7gl1ppzXs/d+FjSg1aAre/lx3KEXCgc126kldS9
|
NesiGalMFDrJvUM1DADTZGQrz9cQVgFq9WTcta9rdTYqSNctxkbpQaY0hgssH1Sh
|
||||||
9+c//UPmltYB17ipVWBmVOyVHNphnHtqPElD9Gz1DooVZ1opsqRBh0APu7fqmm6A
|
hWlSiFttciA2XVD7Ju/Qv9zN4nCQC0LskgKhqsefsOukpo6jqJ92OmNrrNaERfqs
|
||||||
5d/lvNlPrlu835/fgUF3YmyU+w4x5sQCBjprTD6QIbIzCXDXfpBj
|
Yavzuj6DlcnE46ZxA0y2Du1apz0WDlbcAnsEqfNSDDCid09v+V9a
|
||||||
-----END X509 CRL-----
|
-----END X509 CRL-----
|
||||||
|
22
tests/certs/CAcross.pem
Normal file
22
tests/certs/CAcross.pem
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDqTCCApGgAwIBAgIUKFKqG3FwQAmy4HgYyO4mGEiQ8QAwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD1RydXN0ZWQgUm9v
|
||||||
|
dCBDQTAeFw0xODAxMDEwMDAwMDBaFw0zNzEyMjcwMDAwMDBaMFgxCzAJBgNVBAYT
|
||||||
|
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxIDAeBgNVBAsMF0NlcnRpZmljYXRp
|
||||||
|
b24gQXV0aG9yaXR5MRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||||
|
AAOCAQ8AMIIBCgKCAQEAxS8IBYj0uuC1XD1EBFksVv+oHXzrwfzp7KvyghPNeXq7
|
||||||
|
0VJDC8YfUwazNGG4P1MkCPLW4iJU8nt7PZWMpebYb2VRkw8lBG3nRdMZuwYYOLgh
|
||||||
|
NTVbc/4cjm7jkjQgvXhC/9HxfbqWd0HOVjgiagJMA3grN1++gYtoyk29sLU/tria
|
||||||
|
W6Su6aLdYpNECrjoyPkMCqvrc06iVaKa1MH6HRla/7HGeBHtx+j4SKa+E8HvLfGF
|
||||||
|
j04n/buXqYm5AmiHPk+bOFkHKW4yGJxOx3ZwkQpBvuOeKHj3aiQKPq8f8UmYqD4P
|
||||||
|
NcpPK57kqLjaOHMz2/WenIiR3uz+CdlUSwcfqhAi3wIDAQABo2MwYTAPBgNVHRMB
|
||||||
|
Af8EBTADAQH/MB0GA1UdDgQWBBQaPEb++qXSgmAi2vsewtpb6SiIyDAfBgNVHSME
|
||||||
|
GDAWgBSzLyt07qrH3+rgkQCvS/YZ3jR+fzAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZI
|
||||||
|
hvcNAQELBQADggEBADCY4hadNyzoz0CpdpBcFjyglxOkgcitIAgvoc2N5zwHrkg7
|
||||||
|
BgJM1BJmCyki0AhXRKwl7sYbzNHgAhP1pBNjZqO13+cRcqPKvrxpYnsv11HaPS2E
|
||||||
|
Ee/8EwHB3JlWlmWd6PHaJV0usRjDOuJnV/I/9mdFfIUcY0aoA36o2CCRJRKcvvVp
|
||||||
|
Ztomnvw8IqFTn3GCNK3TRmVf2RYMhsDNQoEEidJENwCCRlcojmk1Ld95T89QsGOR
|
||||||
|
cWJAHzyfbMQxRD7kQPZ4B2M8MvU3uD6nsamzvVM7H0UkSNuYLVkpU/wTUR8eQ2LI
|
||||||
|
wFyi9JhKP4hF/RBuSzIHpXWO46GvzAO5dXZPLm0=
|
||||||
|
-----END CERTIFICATE-----
|
22
tests/certs/CAroot.pem
Normal file
22
tests/certs/CAroot.pem
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDsTCCApmgAwIBAgIUQQOniemvgowXmc2hZSZoIWEF8DUwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD1RydXN0ZWQgUm9v
|
||||||
|
dCBDQTAeFw0xNzAxMDEwMDAwMDBaFw0zNjEyMjcwMDAwMDBaMGAxCzAJBgNVBAYT
|
||||||
|
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxIDAeBgNVBAsMF0NlcnRpZmljYXRp
|
||||||
|
b24gQXV0aG9yaXR5MRgwFgYDVQQDDA9UcnVzdGVkIFJvb3QgQ0EwggEiMA0GCSqG
|
||||||
|
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCL2tfObRQcJ4fo/jarNfQVmeqjulYkLLNG
|
||||||
|
UtYmFSAxkcYbmpfHpsSxnW9sbDZV8Cp6tFa97V7XATCNL/r671lpZjkYEj0NkjBE
|
||||||
|
84OI0pkAEwWC5m3+dl3wehu977OcV7cMxNTmAHJwEadXR3jmZV625/lja1QqgkqK
|
||||||
|
MqOty2pJNmsRUEogjFoh00eulnapW5u72ovq9IDgjjhdvAClwkTY5jsLTeDwgvfS
|
||||||
|
MRjAmef2qExI/l760Bl0xe4XDdROgN90npS/zuKcCkThtvmffiUZsyeel1kto1pF
|
||||||
|
zkYGJroWSJl0Jt+dpJHcpSXOXP5M+LnuLV4nl5vqwksdPzswQvuZAgMBAAGjYzBh
|
||||||
|
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLMvK3Tuqsff6uCRAK9L9hneNH5/
|
||||||
|
MB8GA1UdIwQYMBaAFLMvK3Tuqsff6uCRAK9L9hneNH5/MA4GA1UdDwEB/wQEAwIB
|
||||||
|
hjANBgkqhkiG9w0BAQsFAAOCAQEAesmiOEl8OA+T4DDOgjfhY6+pUZDDKpsx//mj
|
||||||
|
/1bxr+akfwL3dN5IBq8g8tJJHOLqrl7Lard7onDRnz8GZmpkPvFa87QD2PU2addo
|
||||||
|
DAQWdYsDrNMWkAE37Wk7FZ0RyFHiBopRUMspKmx/XwvJf+rhkidjJYxCo317i/Z8
|
||||||
|
fWi//wGsI6ogezOsMCxNEcIn2PltGfDiVFklmwsXhyfvGYfctqepu661a/7hFUaP
|
||||||
|
uN0iEboTDcQuiWwwEEwMe55L1rjDlpRkGUBah5FteGmVwk0AoT4b+1FVrj9Q6sEa
|
||||||
|
Ge6gsrhu2syUF9CErTW/CiV+jONe2ygw4welOBo598QW71w7Vw==
|
||||||
|
-----END CERTIFICATE-----
|
@ -1,28 +1,28 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDhMfTdugKYNDCN
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCplbeNvGrZmTDz
|
||||||
opsz9rTpYF710kq3fDN3JdmEFPoZfhZ58CBm+iZBJRCc8KoXMbKAgAZsFaUyU63M
|
p48TyvpOX36bGPMfyTVc8ZfAoh0SG86EFc1LHBV2K52dshHYqniQ6lE14jhsRPps
|
||||||
07fYIxJeu3CTOi7kFQRy5bfGrEOnTBMKUqR+KcOZNeNYtfkv4eca25AtTyziJeBV
|
YRBUFXO7I84Jd5CVcrvBWGuL8wXxjMwIW5buzY4x5oKowlyQGIasNiC8Mgx8TncJ
|
||||||
TOqDoVG5x75ad0+Ab4xA9bhbN4+7m5jS1aJeHtj8eDBkJOIOKGbZ0WEstffAIzWO
|
kVWE6ekgoP4i1f4PVsFyG8zVNpI5VzHArAemYhvDjuA5jgTisfP8ph2pxUKTzYAI
|
||||||
qCC+YFqxsXLO2hOxRgxgpsY9Va4bynn6HW0FZUcUQGEDH0Y17o2KInSyYASad7VI
|
SaKm2YkBFvyhhTxtqnXHt8S0NnfDSCedKSzl1caN1TAKSbWoeChb+Tq8rycjPXh/
|
||||||
F5jjiJnAzzvU701URZ7kjJFGbT9W7523Ljytl/Mvg+5qTG5JNQjVDsWHte6j1Kq8
|
/7TkYgxmlSHiQhRcyEaZs54Ud8Q0nsnfRMhEtewr2IACmuKrFnoS+GtY5glPilR5
|
||||||
bAHpZ6NjAgMBAAECggEBAKDpXmv1FxeE61C5aSc3WMwNxaznZ+Y2RFwV2phrmM4Q
|
ScZ+7A9TAgMBAAECggEABOI/XIzFYMzeg2Rg8DAquQlyc92NE5zPtW0/WxhhizdT
|
||||||
b6UP9Uc/5YfVIUrTGObb5w207WHcEZ+ldWIPwqUZYm34h5dcEtd9QSGMjcXTn7/y
|
bPF3EISXh9DdMimCBeH8XxIzWFfSeFaoNFHp1GCf9ckYRuptk8ppz3OKVhOIbxqr
|
||||||
NwTASrOvygk3HU1tMjKJu+ZQD3Sgx5SMtgCdplEKO2iBlr3z1QYULubX7bSYPgcx
|
YNY9UVVCrEFmjJ0Vxj7Be5M9TTEU4mxLVX4FtmDVClubeOxyX/oqcr4uwme0Az6A
|
||||||
7sOOpEpITayd8HdOkqkqUvLKxAW5xhL2AzBQHaJiGL/zaW0uKEoOVuTrhNw4+Lnw
|
tjBVzl+YEYvZrbhao5d09LVQ3zj1T1EQ+XU5iTTV5Two86FQ6NQ9txe7jxcB8x8S
|
||||||
2IYGrdXpGLAd6hno4kOg2ZkJKWA4Yd+adroeV3BjJ2G1hLJAbPDtS/uB4ZnT1zQx
|
BbD/PakmZj+oIdVBp4xnrhCJ3mYdzXy3qHWxq/BtHgS5fY3/tq3xtVSNxw7QJG7j
|
||||||
OlkqiPgnoH+16I+aLOs7MvIwQ7VRdF46Exk/9qIdHEECgYEA/sUoOQya1/JgPpbd
|
CT2Cps3/99Lq2CPi8OkQKgjJwWqCZ0jOwHahEMlWIQKBgQDneq4LH0zfPJIW2zsi
|
||||||
QeAViTvu9vCFJCnJMkyobG/CVHRDIsNwE/CpaQE+vCn/LpUeKD1KCHIjTOvLF4HM
|
C7U813hV4NuQXd5EW2bmNe4KKnlrcbt3ZtJv8v3Ff5lMm1i8jDCeaeGhZOi/Ag/z
|
||||||
CHt9SECApJESIdexKGP6DVoW+xnomojN/k0YW1JkrnXqmvDw5u/nvFz/JPncKZzB
|
aTtM1STFFEQg3QktcSAvS7hXufvAeufSrPOZdpBO51wqZl5wLMp2lsq885R3wnRl
|
||||||
+Ahx6ocORz+t10V8IRn6SlN0E4MCgYEA4khANwZ0Ys0CwVJkx5+mX3ukgXGsLDcB
|
FtIErdmsLigVMC8RZ++gFNIjMQKBgQC7jJE93wV3j36QA7NAgxNH0AW5p5foWuA8
|
||||||
p1bGrnXhbZOiZxxeWjbR/7b4PyAzsoqxiC/F3RGnU5TEPGnUUeGWv8UFsVsgd8tG
|
gR8MA9cpFI7X7q6hW9HYXw30kD3IzN6UW4U5LT4Pandxx484G1KENcyW2TzeGtpC
|
||||||
QvTOC5iEio6fs/IPZK4Asy4a5ByX6bXjbqSnypN+vf+9lFOvI/+yZ9zKejdoD5Xw
|
MWBWHF4Mbxb/2pEkQoPk1dZmUxF5hvaGGHQYJn/pnJFavGUoNBlNjaIfgStzd1IO
|
||||||
k150XRhWyqECfzDDi+9fekPbIJDaT39MZNLfpd2eK93AIcJ+6b3XplqD5lXBErK+
|
68ceo5URwwKBgGjHJjrQmzo9L5968sRRamM04Tp2QsyRQMfOW8B+ztX5LebNn17H
|
||||||
Xa67jkZ1w2InKJ6LHKCBOECA4V6eeW8mM9Sgg/77xXy0zDPu7u2fUMa/LsZlaQhD
|
wx97bRVV0a1UcBFAn81E/iXRCG1VYKT8kCQSIse2ibQaeUoBd+EQtEu5WtRgjcjW
|
||||||
uWXBX4QFDeKaO4H4aWKkajGpoXpVhsry0tsQ/qqkhaGuqxOq5T1Uu+MCgYEAhz2J
|
Epn3ihC9NwHWPo8mJysQzIpE84JWGducPcpyayI97lTQ761AT741Tn0xAoGARtG2
|
||||||
a5mm+9ntmJ9m7kxDwnOCWX8X2QEzMtFRQ7nedoAzIw84cRCsp/myGwBjBYWRH4T1
|
ioFrhBEoPmNXTZXxMt3HO6qgPvoJ0G8FdTkCBx4fLkSPppiQbb6++0l4Oxm5NpY0
|
||||||
6+9+Ix0Zv8W8iQeb8peNlHeTSyWpo6DueM26AZnGZ2T3wEOi1XRrzAQu4xa7jEhK
|
gTmnRJT0U3+CgjI2/3t9LL0NMeU742DXusxtaw6LxcMXqXSAb2mb0vmtEJG5Bzu2
|
||||||
pG9M47+yjbEKTyimdx7lwO/WeOIze9CLGYzPaqECgYBfgaE2HpG0SYKfDy0ipyxe
|
ouPuyxz2+idHn13E7Db+MB1Ldgdpcf7wKo6knJcCgYBwbcjW0MwCah3w4N4VLXBX
|
||||||
p5ZoGQUXksi7WHSWSTl3tA/0NTtYKCHKb1/hRezjmdRgTuqBaV3y2nF1XmlKw9EX
|
Q5wPSw7cRcytHqrrWkT/nTI3fxwd7UW6ZdM0IwGIAwYgBYD5B78KH0aP6BlUmYWu
|
||||||
nYx/xAfhnyh9K7EZEMtDP2zL6tV1sp6b4Jd7sbFvM/bMJBY6KtKx59Y0u4nkgcH2
|
8vut6S/MsNyCzHQVbcR9BUK3drByzhysVE3TUQKjCA33v6M/tTixhpyPf+ZZtjlK
|
||||||
gt3jad7Axl6C3faOfjzeyw==
|
b1+6D1aGpwt+11f9ubd+Nw==
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
JVHLUWz0r6IIp0mHrMwoI94yZBVXje0=
|
hpE0ajpKT0x/dNa/qCwl/9zc8XxGnPk=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
0mCOiQ==
|
QepMyA==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
Binary file not shown.
@ -2,14 +2,14 @@
|
|||||||
MIICUzCCATsCAQEwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCUEwxFTATBgNV
|
MIICUzCCATsCAQEwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCUEwxFTATBgNV
|
||||||
BAoMDG9zc2xzaWduY29kZTEkMCIGA1UECwwbVGltZXN0YW1wIEF1dGhvcml0eSBS
|
BAoMDG9zc2xzaWduY29kZTEkMCIGA1UECwwbVGltZXN0YW1wIEF1dGhvcml0eSBS
|
||||||
b290IENBMRQwEgYDVQQDDAtUU0EgUm9vdCBDQRcNMTkwMTAxMDAwMDAwWhcNNDMw
|
b290IENBMRQwEgYDVQQDDAtUU0EgUm9vdCBDQRcNMTkwMTAxMDAwMDAwWhcNNDMw
|
||||||
MTAxMDAwMDAwWjB1MCUCFDF3PBReAxISf9HM7Bt0q3GUuBgmFw0yMzA0MjgxMjMz
|
MTAxMDAwMDAwWjB1MCUCFA5lCWy+o133yMUTfqtWmkigL1MeFw0yNDAyMjcxNTMw
|
||||||
NDBaMCUCFElwGj3lGrX4Xg0xaO+y5zAR4MnjFw0yMzA0MjgxMjMzMzlaMCUCFFcV
|
MTVaMCUCFBxm9gh7ZvUWt4Ap+iL+4aRIYkK2Fw0yNDAyMjcxNTMwMTRaMCUCFGs2
|
||||||
Ys5TRUZVMGFWN3Et/yQQme62Fw0yMzA0MjgxMjMzNDBaoDAwLjAfBgNVHSMEGDAW
|
61YG2G/iDfNN1JiSWtAzx0LAFw0yNDAyMjcxNTMwMTRaoDAwLjAfBgNVHSMEGDAW
|
||||||
gBROnw9rl/0Op/SoxQTubQfvoxosZjALBgNVHRQEBAICEAMwDQYJKoZIhvcNAQEL
|
gBQ/Lo89CPWO9O/WTHvV+3Dt/60o+TALBgNVHRQEBAICEAMwDQYJKoZIhvcNAQEL
|
||||||
BQADggEBAEu9tNvUMHJ69vCPdJH3FUuGPHuTyC32aLBoV/g/t9OD+95fDwwijKbX
|
BQADggEBAJ1HK2LepVJyOfqbODFxD6GJo5jr1HEnoaZ1h/iJTZZyDYfRf8d8Y/VG
|
||||||
QcypdgGEp4KEH4WQQ8JyhScgxd3gjnNoB9ITIZ14eZ9uslIZPaQztMDqvzLZcsLf
|
Iva00gj2KVy8tOlO0FrUR1Tqk42IjaPld0lXqKl4hkmCUWLpLgual5JcQPHhDUnT
|
||||||
PXWWvCs8GO1K30VVqVual+OT8ojWBAgF49rg2OZX4JUAhXyaP360MtWEWVNghRwk
|
hiIDvbI5UHGCWeN+unXFRuT9CvtAM+3FOhuL9bBnXwdlOxZPWL8wnYT0jB/HzdKP
|
||||||
FhK7q6HOaNtxrIar1ZuDkvqEvmaEexJ/3HOGAM0DWmhneO2hIpCAfpYnGic66I69
|
KOWfN7eEXo6tTL8XxRJ5LxjwbrK1eZCdQqL2Rt2W8JTMweeqv9PkNqzYeDAvKc0s
|
||||||
17FQWE6WLTS+Hjc8qQEDPeGsSK3NWhGiOKDr1Zpjae5PknghxzfxE8u56t6pMBHj
|
UCkKj+aNxQlNPy+Tw/MckJK1NE921b8LwuV0uzBrOg0Gr62RnnPGa6Z5YLArczWo
|
||||||
DWYGMc57TpovDpTdla7YipkVxSrTkhI=
|
aZlLVsJuQrOxxyXe/kygCu9lqjaf4CI=
|
||||||
-----END X509 CRL-----
|
-----END X509 CRL-----
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
s3UnnC/9NhgSMwB82OPX3g==
|
jkdwUMLiaSrpf8KSTL3NxM0=
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
8e7rP/mN
|
55mIPqG5
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,46 +1,46 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIID7jCCAtagAwIBAgIULWwn/gLcPMAO/7oGqx5A306mxckwDQYJKoZIhvcNAQEL
|
MIID7jCCAtagAwIBAgIUKiF/FG2pQjlbId3ox+nQHL/tJ4UwDQYJKoZIhvcNAQEL
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0yNDEyMzEwMDAwMDBaMIGdMQswCQYDVQQG
|
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0zNDEyMzEwMDAwMDBaMIGdMQswCQYDVQQG
|
||||||
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
||||||
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEUMBIGA1UEAwwL
|
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEUMBIGA1UEAwwL
|
||||||
Q2VydGlmaWNhdGUxJzAlBgkqhkiG9w0BCQEWGG9zc2xzaWduY29kZUBleGFtcGxl
|
Q2VydGlmaWNhdGUxJzAlBgkqhkiG9w0BCQEWGG9zc2xzaWduY29kZUBleGFtcGxl
|
||||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64qSULdxvTp7A4
|
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdBCaytt9xsrUx0
|
||||||
2dl/JbLq7GJ4ZcPbtfUyvVTB5WuntN08bpgnxljON0Ig9lFpN2OOlms/SnodlE6Z
|
2Fekq+IrsR2cC1pL9NANN3TbBv8RKt1IefMh8TjA1uPaOYZvz3o2ml9qKGmJ+uxH
|
||||||
O8GY8kYu/aK3zHIHp3EykzRP1glf7ukcCMpcSaS5VUho0QQ9PVvvMHVNtaQ00r2i
|
kzLojKbg98bcmxBrkWemLQwmRv1hZIO8D4xiYRd0O0KZizrvwWwlNADzXXWw7iz+
|
||||||
34m8DbGj4aRUNI5eA6Xlzz8QnhvCgtRTVbp5ZRjxo1ZNq2eEZxa6UnFshlx6i0/o
|
MPPWkXj2nT5MpOTi3S851SwOc/c9SYCazCP8rMGItKHLO7iCjK3sFwBDI9eaTd2N
|
||||||
kYPrdKTIvUv2zoRFd9H/7+B2Xwse+qppcZe0BiKSa4l6PrL2iHteYE29ggLLSqe+
|
EjqEHadIymHRizeTOaYv34FokQiRgR/zk4flT6+b6DQHxnlbIivV61OP4bBlFtXX
|
||||||
zavGN7Ev7jP+bZLU/5eq58SBy8uFBDkh1FvZEPAnJ2X/vwNzySi6KTliCPc9Jf5G
|
jC4iGdHLIahhVMlw6ixGqR6910psIp0ST0KM8ly+N+1rPhoNkNSLqkzGUudKo7mV
|
||||||
wSJr+5MCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUVeUILLpF5PWz5rAD
|
t+Cp4EMCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQU6a4Ta3t0UCTG04bC
|
||||||
iWzV/2oEP3UwHwYDVR0jBBgwFoAU4/q/jYQJtVH8CIsNnt/ZYq1hcgswEwYDVR0l
|
WMCotMPLyWUwHwYDVR0jBBgwFoAUZBDxqzk33MH9ux3IP0FYd2In7ykwEwYDVR0l
|
||||||
BAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAHckjLcj9mswr08aF7MV
|
BAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAN2Sad4rLRSKWmaRRUCn
|
||||||
EZTKKh0IOaHj7oh6vLR5Yg2n+E+9Gog/+ulbKXNe/5A9QU2R1NdwZKEeUeSuF4qW
|
syRO45y7zzvCRApHVSoeBUmtHP+n/OZ3rJTixfluqiGFAqbaXgTN8IantyfqoTjV
|
||||||
P3JB79BepgR6/VYKyVWH7St4ixy1GtNEFrHWsID212Jd0Rr3+kc9OJUO0aw3nvg7
|
XgCP1qzSM3staLCkeAiZ0/OLW+hyHopP8aXX2ez/hMojB/J1b457+vkuudnNiLx8
|
||||||
Apsr1dztjwlUN2ugLzVoDJ2wMqlu5ZQW8pINIYet127cX5knW/acPCPcqPVD7jmm
|
by44nonUnJb3zyxmCSxcBklNP1wlxYjbbq5hFJ/et2/Y5Ct6igYAEMsYZUEUq3e7
|
||||||
C40xgqeKD2a6OafSS5hjO4UeCoeHnXlJ4Sep8wz8VDlu39Hr4dwFm8v9MuvBusCr
|
g2GWbqNN/i2tnJyGjDPrNRdOuODuclfIDnYSPn83a40XHn+Hgl9SmoXuSdDutAXC
|
||||||
/sdwzTRAc6mhBL/4PyJrBRhibbTxSaDKBHeWcKpmNp4DIk1vc8h6yhDUb1fgafgX
|
b017GsOa7OV3ZPildcIa3d/yk4S3L56SdoY+Py4NIIDmxcjji1e91qCrrFfGYwmg
|
||||||
7nI=
|
TkQ=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDrDCCApSgAwIBAgIUXhcDbb/3vPpWoFCmesKw0dazbzIwDQYJKoZIhvcNAQEL
|
MIIDrDCCApSgAwIBAgIUcRGFYn4pUMRoDtFZhU1EOAPdiWwwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||||
AAOCAQ8AMIIBCgKCAQEA3FMSnznxLiZh2qZ2M4/Y3FcqzNy9XxE1DG5ahUoRifCe
|
AAOCAQ8AMIIBCgKCAQEA5yrw3i+fvxBSODvCoQb+9ibWRozmphJBp57tKv9ZraQ5
|
||||||
LWPGvREPG599ds55MesKqAPo1xAyd7hpQmd+IWzQhvDQntR4BkCQv6PoHQ2WO9co
|
THK+PkCdjNiJuxZn8F1QLsjJo6JqrrXufYln7wixK0Seu4uV6I2TRzcRyJx29D89
|
||||||
CfQ59U5h4pie82IROPHMg31PNYF7MVt2cjBtQco2wvL7XLroYo5nmi20qvsNh53S
|
0G9GrTXKn7v8z32QAqCgtwSZ17uWYTFmRAYPllWXcWDONsVyw3UF2nClndL7GMqM
|
||||||
nJ0vGsIhdBd5UVn7S5NghHYF03cmFiZVuSvN3ovFl1k0iIH+eJdfYXBiTqtcUCAc
|
gDizlwsfg8HmRpZegn82I7Y2DXccm9a7pFHuBHpwenKqfBnMsXo3Jj4Xlr1cLTrh
|
||||||
0+ngTui3LWd18QB6M6HYdT1a0MihGs1g0RE7ni2C5iwBn4FOe+eHzZOq5AcWVGR4
|
+6ksS5YogOsOd9b5Dfz6FaGmmwrlUWHwdi+EzdnSpOnXzmgflF23sZQ0ynsVvmpl
|
||||||
ZSvDc+6O22sy0esBYsPElJBnQLOPyIRwd4B8MO6PewIDAQABo2YwZDASBgNVHRMB
|
iD4rXBWnxnQ6Ken3wVPNrA/0ZYGbgSKrcv+/olkh5QIDAQABo2YwZDASBgNVHRMB
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBTj+r+NhAm1UfwIiw2e39lirWFyCzAfBgNV
|
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRkEPGrOTfcwf27Hcg/QVh3YifvKTAfBgNV
|
||||||
HSMEGDAWgBRYinOUkj6959wnBw0YfDBGaz/adzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
HSMEGDAWgBQaPEb++qXSgmAi2vsewtpb6SiIyDAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
||||||
KoZIhvcNAQELBQADggEBACn3BOVCATol6TC31cKPvh9hOOq9uvgREGG1paTmZNhe
|
KoZIhvcNAQELBQADggEBAL22kK3SDGnr3lhRE7ipptlKalrQKfpght0XEKm5hxCL
|
||||||
JsrIUkD2KZN7dpAJEJF7uu2LaCm0F5VqQUj3SdYHD3neHiOeO8jzgM4BWgqZ3lZc
|
tougN2wtaTEWMwr2YfGJohcKBaGKQ+Bv6WY+EV+hJE4qEUFh6BGqRMtuZdiAbkG+
|
||||||
FQfGbNoR4QQMADMJYKJ/LCRjBKUrHDvkvuQHkb+y8yUg1UtNpeH3cFty2/eo7VWD
|
EveEMhZWQzgf9rUID+Y9Eg+NfCxlpkdQPjUxUV9OkGIshlxkUP8Y+C0h0xIcwq5v
|
||||||
Su5Jd1vVIo4XkQDBPr5UR9LVSMfhvhX4pcvijmETTEYn3ZZ2KeF1q5JC1Le+322Q
|
hAfNiJAdcw4fUvtLkpEOFoOjThB8zxOu+Cl3xLCcNOMPLdSxd3YXjy6CMuuOk4RB
|
||||||
xwgVhiJak3GUh06mYQf6qFSRanu78Jeyw8IlsS+o8V9W+dqYYDOENDYNJGB5MaS/
|
gOc8YCyyEvwb9KmARZpMOcQJmucMhs+aC3DF+n71g+agFhDl3Z0QkyyyRjAcD04+
|
||||||
yAA20r1RAb2RmPPbpiPjR2FKzNDxu7nHd4EecbSevdE=
|
sAR9C8PbqSCQAdydHbAFViEX6x3oGJ7L6zEDcIS10wg=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
Binary file not shown.
@ -1,47 +1,47 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIEPTCCAyWgAwIBAgIUZp72ahjzVryMA56ev7+Z8Rxyo2kwDQYJKoZIhvcNAQEL
|
MIIEPTCCAyWgAwIBAgIUe8Im9GuMCHMi3/FDfLgzoE8vTKgwDQYJKoZIhvcNAQEL
|
||||||
BQAwZzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwZzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMMFkludGVybWVkaWF0
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMMFkludGVybWVkaWF0
|
||||||
ZSBDQSBDUkwgRFAwHhcNMTgwMTAxMDAwMDAwWhcNMjQxMjMxMDAwMDAwWjCBqzEL
|
ZSBDQSBDUkwgRFAwHhcNMTgwMTAxMDAwMDAwWhcNMzQxMjMxMDAwMDAwWjCBqzEL
|
||||||
MAkGA1UEBhMCUEwxGTAXBgNVBAgMEE1hem92aWEgUHJvdmluY2UxDzANBgNVBAcM
|
MAkGA1UEBhMCUEwxGTAXBgNVBAgMEE1hem92aWEgUHJvdmluY2UxDzANBgNVBAcM
|
||||||
BldhcnNhdzEVMBMGA1UECgwMb3NzbHNpZ25jb2RlMQwwCgYDVQQLDANDU1AxIjAg
|
BldhcnNhdzEVMBMGA1UECgwMb3NzbHNpZ25jb2RlMQwwCgYDVQQLDANDU1AxIjAg
|
||||||
BgNVBAMMGUNlcnRpZmljYXRlIFg1MDl2MyBDUkwgRFAxJzAlBgkqhkiG9w0BCQEW
|
BgNVBAMMGUNlcnRpZmljYXRlIFg1MDl2MyBDUkwgRFAxJzAlBgkqhkiG9w0BCQEW
|
||||||
GG9zc2xzaWduY29kZUBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
GG9zc2xzaWduY29kZUBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||||
ADCCAQoCggEBAL64qSULdxvTp7A42dl/JbLq7GJ4ZcPbtfUyvVTB5WuntN08bpgn
|
ADCCAQoCggEBAMdBCaytt9xsrUx02Fekq+IrsR2cC1pL9NANN3TbBv8RKt1IefMh
|
||||||
xljON0Ig9lFpN2OOlms/SnodlE6ZO8GY8kYu/aK3zHIHp3EykzRP1glf7ukcCMpc
|
8TjA1uPaOYZvz3o2ml9qKGmJ+uxHkzLojKbg98bcmxBrkWemLQwmRv1hZIO8D4xi
|
||||||
SaS5VUho0QQ9PVvvMHVNtaQ00r2i34m8DbGj4aRUNI5eA6Xlzz8QnhvCgtRTVbp5
|
YRd0O0KZizrvwWwlNADzXXWw7iz+MPPWkXj2nT5MpOTi3S851SwOc/c9SYCazCP8
|
||||||
ZRjxo1ZNq2eEZxa6UnFshlx6i0/okYPrdKTIvUv2zoRFd9H/7+B2Xwse+qppcZe0
|
rMGItKHLO7iCjK3sFwBDI9eaTd2NEjqEHadIymHRizeTOaYv34FokQiRgR/zk4fl
|
||||||
BiKSa4l6PrL2iHteYE29ggLLSqe+zavGN7Ev7jP+bZLU/5eq58SBy8uFBDkh1FvZ
|
T6+b6DQHxnlbIivV61OP4bBlFtXXjC4iGdHLIahhVMlw6ixGqR6910psIp0ST0KM
|
||||||
EPAnJ2X/vwNzySi6KTliCPc9Jf5GwSJr+5MCAwEAAaOBmzCBmDAJBgNVHRMEAjAA
|
8ly+N+1rPhoNkNSLqkzGUudKo7mVt+Cp4EMCAwEAAaOBmzCBmDAJBgNVHRMEAjAA
|
||||||
MB0GA1UdDgQWBBRV5QgsukXk9bPmsAOJbNX/agQ/dTAfBgNVHSMEGDAWgBRhu0A6
|
MB0GA1UdDgQWBBTprhNre3RQJMbThsJYwKi0w8vJZTAfBgNVHSMEGDAWgBQUPGKp
|
||||||
SceOaK7eXw40BRjfzuQWLzATBgNVHSUEDDAKBggrBgEFBQcDAzA2BgNVHR8ELzAt
|
4nGIluZnh6sofSkEiGrtIzATBgNVHSUEDDAKBggrBgEFBQcDAzA2BgNVHR8ELzAt
|
||||||
MCugKaAnhiVodHRwOi8vMTI3LjAuMC4xOjE5MjU0L2ludGVybWVkaWF0ZUNBMA0G
|
MCugKaAnhiVodHRwOi8vMTI3LjAuMC4xOjE5MjU0L2ludGVybWVkaWF0ZUNBMA0G
|
||||||
CSqGSIb3DQEBCwUAA4IBAQC2yNGXw1VZqBWY7cnJtiZpupKYCifRC1dEFlKcozpd
|
CSqGSIb3DQEBCwUAA4IBAQBlJrcOaJQQ3TuYaVtmH8VbCdF3GQE+255g0Kq4sWoO
|
||||||
dhWHDKpGDCzqaL/WKpqFjOIrCbG6gsfB+nu2VQv4nE8lwwelMgpeVB+v197A1SvE
|
ZgZm6LmRkchuoOXqeZ7aAV6HnGGpZf64ShPSZ3KPt4/UVYkRyS0UihN2ACsGrS4o
|
||||||
wLl71R5a7sxF0x5aBdUyWeCTeBLu6KuWQrpPcZVM3uMqhqCJ8CiSUtS1cKn1K1K0
|
ZjOaaoM2xDxttngKV3lAF4xbx18RvAsx9QIzQhzowaSUBQNuu5W4tne/6h7htuwA
|
||||||
KRSgFTs4AFUc0rOa3wYvytps4cw/TyDXArlvGVMlDHNLffEsx3vElZafaGvyEK0J
|
KNc0go4fqpCqQjNRVeB1IN50BzUrlHu3zQzfH0LDyUTt2gnObLHMl566Ft0azAG9
|
||||||
TsBM2dakcpP/ceuJU1gd8hLadzjfKOFml7z+qHfUa/mky+veK2M5vKn1ph55qYHc
|
emHRM+BOUjKY3ZTjM+JEzpwWgse6e4r+J2fYVYIEtkSfm4ZZnAs5WFWI5o8tqr4b
|
||||||
WtEY/wwBjgqE2VseqMLb06J3tXmTKgESGXISAnqoau+t
|
ruBN7l6oP6R3ugOtPk7tW4x7OO0QoDnfa418MkBlXeqL
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDszCCApugAwIBAgIUdUqeYLe6em9A4BIXcQhE2lS8KTUwDQYJKoZIhvcNAQEL
|
MIIDszCCApugAwIBAgIUN3RBnJCUJ8HmbeNjJZ/6jsXJLGEwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBnMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBnMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEfMB0GA1UEAwwWSW50ZXJtZWRpYXRlIENBIENSTCBEUDCCASIwDQYJKoZI
|
cml0eTEfMB0GA1UEAwwWSW50ZXJtZWRpYXRlIENBIENSTCBEUDCCASIwDQYJKoZI
|
||||||
hvcNAQEBBQADggEPADCCAQoCggEBANoHRxZ1qxQKLm8MLYswvTf9FBq05unFxE9j
|
hvcNAQEBBQADggEPADCCAQoCggEBAME32IBpxW4FhVuZe1PTarEskVHP233QjZtx
|
||||||
nea4njWqBkg3cT/jZo2sDHlkN+q3BFEL/K+mej0/LqfW6eXrskHj6OLyXas2/HR4
|
poC67/lUK44gtFmsxYsMrDYmmny5pfoM/Byxl5/rorEddLqtDe1kd1SpXUvEYxox
|
||||||
UYsby8djwazvt4LLiMS5yfo3GlRv5p44F1ruYu7/km7J/6pUxQMB+lTXKA4TzUWe
|
s5rizRd5sZPgkwNoJkSVyNZFwj7gKZHeg6IQHSxNgmTybZ+eZqiNvEveksj3lGpM
|
||||||
n/xa2xGm0ZDXvQC1GlPJ1mD/fm0JeS6g8iMdTfvKPKKFMArz+wGWBiqbAKnmuDfp
|
Xrbiew7cXUyIP636GPtYxLyIbwDVP0jScqcA/dmSAqofFVUi0SW3OS1hpyXAmmx8
|
||||||
J3j64nWyRCArH+tGgvOmqkXAUBh9A0T1AfdF1Q5kFKzFq38zKI6lPELo0qEio9SO
|
hQHJRKPjPgitZVgjwf5X8/eMTa+ca9dRlRFLk7AcbkF6NcbLm+cRo816nO0EBFV4
|
||||||
W+aOVVDtknTXmqKtawFyhn2e3UEzISYmFv2Wfc/dLnmBzRLNR9cCAwEAAaNmMGQw
|
Sn2dW9uYqJIfZcpRQ7wbv4fUCghwrk9h3gXrb7AweyK8nyYlmosCAwEAAaNmMGQw
|
||||||
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUYbtAOknHjmiu3l8ONAUY387k
|
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUFDxiqeJxiJbmZ4erKH0pBIhq
|
||||||
Fi8wHwYDVR0jBBgwFoAUWIpzlJI+vefcJwcNGHwwRms/2ncwDgYDVR0PAQH/BAQD
|
7SMwHwYDVR0jBBgwFoAUGjxG/vql0oJgItr7HsLaW+koiMgwDgYDVR0PAQH/BAQD
|
||||||
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBJ69rsOHP4qKnu/wRS/D3fV/voLHB624Rg
|
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQAlI/1XnGc9WzL53rRascZc1EgWAnej9YFS
|
||||||
RpC4RshZMPVL60LaouJo1GMHj3IwyHVHGFkTxGYP0IIgcMUCnkmpSfX1tahYU+kB
|
Dax5+nozYTihC8BRxGfSh1FGRVsmFWhZ0z0XogJJC2bZrQ/36+vwoILItcsWHrQr
|
||||||
4fSCxheLg79g2y3Z1jTQxFOvRjn5t4BIk4Rq4o9E7n1x+8jcaCBSjmna9j6i5lgA
|
rFoZa6s1Uo7ZCd9SfmXjbhMLQgydocCh9YIF66CAkQLwRXc1QIpF7nuZ+rxk0ru1
|
||||||
QjazvdXrhhgrkvvMtk2wtk1laiHUHFgb9zxzNhhZFzy+QXwQv+Zj1N0swKfTP2gK
|
uGjjBrFRfdSdzlFnyK6wfFzi6LtYDVgVEHC7zzL9E/cyuGo7qQ++SoOg99HjTVY1
|
||||||
Rxls7e47SnMdvthINZpdvUwT5pBZnMKHqgQK6YbWcopBpuw7zOTJp6Ghqzqzwa4d
|
PS3ea522bRO2bJpYwZJvvbg020DAfm686VXwAadODdBkI2h6U5SwTxp4SkSmq9SI
|
||||||
CwUtEB7f0e7dWeG7DFJ2cNPcpXaigNtvfdRR3W1RduX9FCODihFF
|
mjtERFtnAKD0R2YrX4RzuIckezvwsqLDkQjMnI9XQmv5HWUZimcC
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDzjCCAragAwIBAgIUKUVnRllbtypXICoznroWil39jU4wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwbzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEMMAoGA1UE
|
|
||||||
CwwDQ1NQMRIwEAYDVQQDDAljcm9zc2NlcnQxJzAlBgkqhkiG9w0BCQEWGG9zc2xz
|
|
||||||
aWduY29kZUBleGFtcGxlLmNvbTAeFw0xODAxMDEwMDAwMDBaFw0yMDA2MTkwMDAw
|
|
||||||
MDBaMG8xCzAJBgNVBAYTAlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNV
|
|
||||||
BAsMA0NTUDESMBAGA1UEAwwJY3Jvc3NjZXJ0MScwJQYJKoZIhvcNAQkBFhhvc3Ns
|
|
||||||
c2lnbmNvZGVAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
|
||||||
AoIBAQDFCjBrTLeh9wyMb6tJi1SMz+Pe6Eb8SCg4+soxBAu1EEVo4Ao810j2NVdc
|
|
||||||
aoQ2Ki097hl9LHcA0DMT8AFRHfXMXHSSHoYHsPcwHO6RJHXcDE4fSgkl41GtCnf+
|
|
||||||
qUOA+QZUqNNKNOELUHboydFMytNGjuSaO29BObkiHCRB8gnfKuqGZn9YrfU8AoGu
|
|
||||||
xv7RzKgD+uC/dTZSONAW+h7TuRn4/qtqTqfk5SnmTeEDbW3lyYLToRRKUKcYR68a
|
|
||||||
lT/IZ2cHCrZMqvykR2cCMCARbTyI8ZQ6ogzXS/tncJYu/RTtEoKiN1EweG5R0cgU
|
|
||||||
G0xQISw5RXMUSgWkWUL8rYpFcmahAgMBAAGjYjBgMAkGA1UdEwQCMAAwHQYDVR0O
|
|
||||||
BBYEFBt9u2LhSzaQrQLcja2QtFexM2tKMB8GA1UdIwQYMBaAFBt9u2LhSzaQrQLc
|
|
||||||
ja2QtFexM2tKMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IB
|
|
||||||
AQATfeXQ2kj+97IHUOtFZTjcIH47U6k8Po11WD+Af4PRmacOKaSv+rlmgpgHfQJV
|
|
||||||
nM90mxUvKzaoJeId/yR++U86rcu8a87njHoyDzx2HMcc47P/2VkErT9W4gyJE0Ws
|
|
||||||
JyIR0k0XZiYJ+pJOSjnd7SY2gs1oBT3+Go5TyClAfzAP+U10fK52q802XNPw5MY0
|
|
||||||
LEyRqCH4QYb71Hd4kGqROVy1EPv18d26apD9vK/zZuvOsbz23l0mdochYrtmfAA0
|
|
||||||
LuNwefIgxzki22+bZe7lJyuV5WsqSNGVty+fvqmw9JUfzeOpIzVK/SxqANJnZBBI
|
|
||||||
kapgFmTwk4JEfB3n2WTmbs9C
|
|
||||||
-----END CERTIFICATE-----
|
|
@ -1,45 +1,45 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIID6jCCAtKgAwIBAgIUW4SefwoiLUfTBaHpZyd8knsGVBswDQYJKoZIhvcNAQEL
|
MIID6jCCAtKgAwIBAgIUcgUgRT1Lx8XLdgp7xcWxVl9YBjYwDQYJKoZIhvcNAQEL
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMIGZMQswCQYDVQQG
|
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMIGZMQswCQYDVQQG
|
||||||
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
||||||
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UEAwwH
|
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UEAwwH
|
||||||
RXhwaXJlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUuY29t
|
RXhwaXJlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUuY29t
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvripJQt3G9OnsDjZ2X8l
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx0EJrK233GytTHTYV6Sr
|
||||||
sursYnhlw9u19TK9VMHla6e03TxumCfGWM43QiD2UWk3Y46Waz9Keh2UTpk7wZjy
|
4iuxHZwLWkv00A03dNsG/xEq3Uh58yHxOMDW49o5hm/PejaaX2ooaYn67EeTMuiM
|
||||||
Ri79orfMcgencTKTNE/WCV/u6RwIylxJpLlVSGjRBD09W+8wdU21pDTSvaLfibwN
|
puD3xtybEGuRZ6YtDCZG/WFkg7wPjGJhF3Q7QpmLOu/BbCU0APNddbDuLP4w89aR
|
||||||
saPhpFQ0jl4DpeXPPxCeG8KC1FNVunllGPGjVk2rZ4RnFrpScWyGXHqLT+iRg+t0
|
ePadPkyk5OLdLznVLA5z9z1JgJrMI/yswYi0ocs7uIKMrewXAEMj15pN3Y0SOoQd
|
||||||
pMi9S/bOhEV30f/v4HZfCx76qmlxl7QGIpJriXo+svaIe15gTb2CAstKp77Nq8Y3
|
p0jKYdGLN5M5pi/fgWiRCJGBH/OTh+VPr5voNAfGeVsiK9XrU4/hsGUW1deMLiIZ
|
||||||
sS/uM/5tktT/l6rnxIHLy4UEOSHUW9kQ8CcnZf+/A3PJKLopOWII9z0l/kbBImv7
|
0cshqGFUyXDqLEapHr3XSmwinRJPQozyXL437Ws+Gg2Q1IuqTMZS50qjuZW34Kng
|
||||||
kwIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBRV5QgsukXk9bPmsAOJbNX/
|
QwIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBTprhNre3RQJMbThsJYwKi0
|
||||||
agQ/dTAfBgNVHSMEGDAWgBTj+r+NhAm1UfwIiw2e39lirWFyCzATBgNVHSUEDDAK
|
w8vJZTAfBgNVHSMEGDAWgBRkEPGrOTfcwf27Hcg/QVh3YifvKTATBgNVHSUEDDAK
|
||||||
BggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAp06uHnxO63Ecn+knaXkfrNGg
|
BggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEA0AxgPkboWfIOMYFOP6kQ4nxY
|
||||||
pr+4WCc0onXYOE37+IwsCFaUqCIr1UsnnKWSzSlSR07FHI+VaV9r3knT6VPMVsUU
|
jQ+kAH842ALjm/5z20fYPS0k3LiCNS0FfBPzygeWQLwDGcH2QX6Lfec62CeIe9R9
|
||||||
L89jHC2vLUvyJJOtuTpuOVGIzzCquYWvYRZrp2wmTceMSNhLcO1VGs28uwQojWEQ
|
IAdsX+nNxn9FeIZssfMK3EPgksGUybUNub78mXPrnhCNjYf/GmDY/Cf7jhBtNphK
|
||||||
ZsEdFvkYeWFInUQ1mF0dLnfQjh7RcTxMJ0CxZblJ086j3AbyzM6ZF6XAVPAqBH/S
|
6zCPOC0WDrupnLW7r4FyrB1j2CEgaHhiSmlQ+19rqbvcNfaCOMfe7IfiwkvVIzE6
|
||||||
gsBfLVGnZnMOwvKwsxViG1ikRusO6GtcIy6yxmNCUhWbIL+R59EYy++x3xLVUU90
|
tQhnudB/HnW3+pWT83n/KQk0F8lu00fahkak/0bPidTe4zOvepabiWYQXKJ9ZXhm
|
||||||
YnScDN+xM9A2wHO1hQpLK6DIiHpbAzAgll5xD0JWh+efRWHEtGN5JTybowG9yA==
|
UW7FHHSM5Vbn2A6zyEht7rcK/gkpHbkckoIi6bDMFMp+K9o3qV7PzZPkaau7fg==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDrDCCApSgAwIBAgIUXhcDbb/3vPpWoFCmesKw0dazbzIwDQYJKoZIhvcNAQEL
|
MIIDrDCCApSgAwIBAgIUcRGFYn4pUMRoDtFZhU1EOAPdiWwwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||||
AAOCAQ8AMIIBCgKCAQEA3FMSnznxLiZh2qZ2M4/Y3FcqzNy9XxE1DG5ahUoRifCe
|
AAOCAQ8AMIIBCgKCAQEA5yrw3i+fvxBSODvCoQb+9ibWRozmphJBp57tKv9ZraQ5
|
||||||
LWPGvREPG599ds55MesKqAPo1xAyd7hpQmd+IWzQhvDQntR4BkCQv6PoHQ2WO9co
|
THK+PkCdjNiJuxZn8F1QLsjJo6JqrrXufYln7wixK0Seu4uV6I2TRzcRyJx29D89
|
||||||
CfQ59U5h4pie82IROPHMg31PNYF7MVt2cjBtQco2wvL7XLroYo5nmi20qvsNh53S
|
0G9GrTXKn7v8z32QAqCgtwSZ17uWYTFmRAYPllWXcWDONsVyw3UF2nClndL7GMqM
|
||||||
nJ0vGsIhdBd5UVn7S5NghHYF03cmFiZVuSvN3ovFl1k0iIH+eJdfYXBiTqtcUCAc
|
gDizlwsfg8HmRpZegn82I7Y2DXccm9a7pFHuBHpwenKqfBnMsXo3Jj4Xlr1cLTrh
|
||||||
0+ngTui3LWd18QB6M6HYdT1a0MihGs1g0RE7ni2C5iwBn4FOe+eHzZOq5AcWVGR4
|
+6ksS5YogOsOd9b5Dfz6FaGmmwrlUWHwdi+EzdnSpOnXzmgflF23sZQ0ynsVvmpl
|
||||||
ZSvDc+6O22sy0esBYsPElJBnQLOPyIRwd4B8MO6PewIDAQABo2YwZDASBgNVHRMB
|
iD4rXBWnxnQ6Ken3wVPNrA/0ZYGbgSKrcv+/olkh5QIDAQABo2YwZDASBgNVHRMB
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBTj+r+NhAm1UfwIiw2e39lirWFyCzAfBgNV
|
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRkEPGrOTfcwf27Hcg/QVh3YifvKTAfBgNV
|
||||||
HSMEGDAWgBRYinOUkj6959wnBw0YfDBGaz/adzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
HSMEGDAWgBQaPEb++qXSgmAi2vsewtpb6SiIyDAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
||||||
KoZIhvcNAQELBQADggEBACn3BOVCATol6TC31cKPvh9hOOq9uvgREGG1paTmZNhe
|
KoZIhvcNAQELBQADggEBAL22kK3SDGnr3lhRE7ipptlKalrQKfpght0XEKm5hxCL
|
||||||
JsrIUkD2KZN7dpAJEJF7uu2LaCm0F5VqQUj3SdYHD3neHiOeO8jzgM4BWgqZ3lZc
|
tougN2wtaTEWMwr2YfGJohcKBaGKQ+Bv6WY+EV+hJE4qEUFh6BGqRMtuZdiAbkG+
|
||||||
FQfGbNoR4QQMADMJYKJ/LCRjBKUrHDvkvuQHkb+y8yUg1UtNpeH3cFty2/eo7VWD
|
EveEMhZWQzgf9rUID+Y9Eg+NfCxlpkdQPjUxUV9OkGIshlxkUP8Y+C0h0xIcwq5v
|
||||||
Su5Jd1vVIo4XkQDBPr5UR9LVSMfhvhX4pcvijmETTEYn3ZZ2KeF1q5JC1Le+322Q
|
hAfNiJAdcw4fUvtLkpEOFoOjThB8zxOu+Cl3xLCcNOMPLdSxd3YXjy6CMuuOk4RB
|
||||||
xwgVhiJak3GUh06mYQf6qFSRanu78Jeyw8IlsS+o8V9W+dqYYDOENDYNJGB5MaS/
|
gOc8YCyyEvwb9KmARZpMOcQJmucMhs+aC3DF+n71g+agFhDl3Z0QkyyyRjAcD04+
|
||||||
yAA20r1RAb2RmPPbpiPjR2FKzNDxu7nHd4EecbSevdE=
|
sAR9C8PbqSCQAdydHbAFViEX6x3oGJ7L6zEDcIS10wg=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDrDCCApSgAwIBAgIUXhcDbb/3vPpWoFCmesKw0dazbzIwDQYJKoZIhvcNAQEL
|
MIIDrDCCApSgAwIBAgIUcRGFYn4pUMRoDtFZhU1EOAPdiWwwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||||
AAOCAQ8AMIIBCgKCAQEA3FMSnznxLiZh2qZ2M4/Y3FcqzNy9XxE1DG5ahUoRifCe
|
AAOCAQ8AMIIBCgKCAQEA5yrw3i+fvxBSODvCoQb+9ibWRozmphJBp57tKv9ZraQ5
|
||||||
LWPGvREPG599ds55MesKqAPo1xAyd7hpQmd+IWzQhvDQntR4BkCQv6PoHQ2WO9co
|
THK+PkCdjNiJuxZn8F1QLsjJo6JqrrXufYln7wixK0Seu4uV6I2TRzcRyJx29D89
|
||||||
CfQ59U5h4pie82IROPHMg31PNYF7MVt2cjBtQco2wvL7XLroYo5nmi20qvsNh53S
|
0G9GrTXKn7v8z32QAqCgtwSZ17uWYTFmRAYPllWXcWDONsVyw3UF2nClndL7GMqM
|
||||||
nJ0vGsIhdBd5UVn7S5NghHYF03cmFiZVuSvN3ovFl1k0iIH+eJdfYXBiTqtcUCAc
|
gDizlwsfg8HmRpZegn82I7Y2DXccm9a7pFHuBHpwenKqfBnMsXo3Jj4Xlr1cLTrh
|
||||||
0+ngTui3LWd18QB6M6HYdT1a0MihGs1g0RE7ni2C5iwBn4FOe+eHzZOq5AcWVGR4
|
+6ksS5YogOsOd9b5Dfz6FaGmmwrlUWHwdi+EzdnSpOnXzmgflF23sZQ0ynsVvmpl
|
||||||
ZSvDc+6O22sy0esBYsPElJBnQLOPyIRwd4B8MO6PewIDAQABo2YwZDASBgNVHRMB
|
iD4rXBWnxnQ6Ken3wVPNrA/0ZYGbgSKrcv+/olkh5QIDAQABo2YwZDASBgNVHRMB
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBTj+r+NhAm1UfwIiw2e39lirWFyCzAfBgNV
|
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRkEPGrOTfcwf27Hcg/QVh3YifvKTAfBgNV
|
||||||
HSMEGDAWgBRYinOUkj6959wnBw0YfDBGaz/adzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
HSMEGDAWgBQaPEb++qXSgmAi2vsewtpb6SiIyDAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
||||||
KoZIhvcNAQELBQADggEBACn3BOVCATol6TC31cKPvh9hOOq9uvgREGG1paTmZNhe
|
KoZIhvcNAQELBQADggEBAL22kK3SDGnr3lhRE7ipptlKalrQKfpght0XEKm5hxCL
|
||||||
JsrIUkD2KZN7dpAJEJF7uu2LaCm0F5VqQUj3SdYHD3neHiOeO8jzgM4BWgqZ3lZc
|
tougN2wtaTEWMwr2YfGJohcKBaGKQ+Bv6WY+EV+hJE4qEUFh6BGqRMtuZdiAbkG+
|
||||||
FQfGbNoR4QQMADMJYKJ/LCRjBKUrHDvkvuQHkb+y8yUg1UtNpeH3cFty2/eo7VWD
|
EveEMhZWQzgf9rUID+Y9Eg+NfCxlpkdQPjUxUV9OkGIshlxkUP8Y+C0h0xIcwq5v
|
||||||
Su5Jd1vVIo4XkQDBPr5UR9LVSMfhvhX4pcvijmETTEYn3ZZ2KeF1q5JC1Le+322Q
|
hAfNiJAdcw4fUvtLkpEOFoOjThB8zxOu+Cl3xLCcNOMPLdSxd3YXjy6CMuuOk4RB
|
||||||
xwgVhiJak3GUh06mYQf6qFSRanu78Jeyw8IlsS+o8V9W+dqYYDOENDYNJGB5MaS/
|
gOc8YCyyEvwb9KmARZpMOcQJmucMhs+aC3DF+n71g+agFhDl3Z0QkyyyRjAcD04+
|
||||||
yAA20r1RAb2RmPPbpiPjR2FKzNDxu7nHd4EecbSevdE=
|
sAR9C8PbqSCQAdydHbAFViEX6x3oGJ7L6zEDcIS10wg=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDszCCApugAwIBAgIUdUqeYLe6em9A4BIXcQhE2lS8KTUwDQYJKoZIhvcNAQEL
|
MIIDszCCApugAwIBAgIUN3RBnJCUJ8HmbeNjJZ/6jsXJLGEwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBnMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBnMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEfMB0GA1UEAwwWSW50ZXJtZWRpYXRlIENBIENSTCBEUDCCASIwDQYJKoZI
|
cml0eTEfMB0GA1UEAwwWSW50ZXJtZWRpYXRlIENBIENSTCBEUDCCASIwDQYJKoZI
|
||||||
hvcNAQEBBQADggEPADCCAQoCggEBANoHRxZ1qxQKLm8MLYswvTf9FBq05unFxE9j
|
hvcNAQEBBQADggEPADCCAQoCggEBAME32IBpxW4FhVuZe1PTarEskVHP233QjZtx
|
||||||
nea4njWqBkg3cT/jZo2sDHlkN+q3BFEL/K+mej0/LqfW6eXrskHj6OLyXas2/HR4
|
poC67/lUK44gtFmsxYsMrDYmmny5pfoM/Byxl5/rorEddLqtDe1kd1SpXUvEYxox
|
||||||
UYsby8djwazvt4LLiMS5yfo3GlRv5p44F1ruYu7/km7J/6pUxQMB+lTXKA4TzUWe
|
s5rizRd5sZPgkwNoJkSVyNZFwj7gKZHeg6IQHSxNgmTybZ+eZqiNvEveksj3lGpM
|
||||||
n/xa2xGm0ZDXvQC1GlPJ1mD/fm0JeS6g8iMdTfvKPKKFMArz+wGWBiqbAKnmuDfp
|
Xrbiew7cXUyIP636GPtYxLyIbwDVP0jScqcA/dmSAqofFVUi0SW3OS1hpyXAmmx8
|
||||||
J3j64nWyRCArH+tGgvOmqkXAUBh9A0T1AfdF1Q5kFKzFq38zKI6lPELo0qEio9SO
|
hQHJRKPjPgitZVgjwf5X8/eMTa+ca9dRlRFLk7AcbkF6NcbLm+cRo816nO0EBFV4
|
||||||
W+aOVVDtknTXmqKtawFyhn2e3UEzISYmFv2Wfc/dLnmBzRLNR9cCAwEAAaNmMGQw
|
Sn2dW9uYqJIfZcpRQ7wbv4fUCghwrk9h3gXrb7AweyK8nyYlmosCAwEAAaNmMGQw
|
||||||
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUYbtAOknHjmiu3l8ONAUY387k
|
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUFDxiqeJxiJbmZ4erKH0pBIhq
|
||||||
Fi8wHwYDVR0jBBgwFoAUWIpzlJI+vefcJwcNGHwwRms/2ncwDgYDVR0PAQH/BAQD
|
7SMwHwYDVR0jBBgwFoAUGjxG/vql0oJgItr7HsLaW+koiMgwDgYDVR0PAQH/BAQD
|
||||||
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBJ69rsOHP4qKnu/wRS/D3fV/voLHB624Rg
|
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQAlI/1XnGc9WzL53rRascZc1EgWAnej9YFS
|
||||||
RpC4RshZMPVL60LaouJo1GMHj3IwyHVHGFkTxGYP0IIgcMUCnkmpSfX1tahYU+kB
|
Dax5+nozYTihC8BRxGfSh1FGRVsmFWhZ0z0XogJJC2bZrQ/36+vwoILItcsWHrQr
|
||||||
4fSCxheLg79g2y3Z1jTQxFOvRjn5t4BIk4Rq4o9E7n1x+8jcaCBSjmna9j6i5lgA
|
rFoZa6s1Uo7ZCd9SfmXjbhMLQgydocCh9YIF66CAkQLwRXc1QIpF7nuZ+rxk0ru1
|
||||||
QjazvdXrhhgrkvvMtk2wtk1laiHUHFgb9zxzNhhZFzy+QXwQv+Zj1N0swKfTP2gK
|
uGjjBrFRfdSdzlFnyK6wfFzi6LtYDVgVEHC7zzL9E/cyuGo7qQ++SoOg99HjTVY1
|
||||||
Rxls7e47SnMdvthINZpdvUwT5pBZnMKHqgQK6YbWcopBpuw7zOTJp6Ghqzqzwa4d
|
PS3ea522bRO2bJpYwZJvvbg020DAfm686VXwAadODdBkI2h6U5SwTxp4SkSmq9SI
|
||||||
CwUtEB7f0e7dWeG7DFJ2cNPcpXaigNtvfdRR3W1RduX9FCODihFF
|
mjtERFtnAKD0R2YrX4RzuIckezvwsqLDkQjMnI9XQmv5HWUZimcC
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
Binary file not shown.
@ -1,27 +1,28 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
-----END RSA PRIVATE KEY-----
|
GlIpzzm+MYzra4yB4VpRw5ES
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
Binary file not shown.
@ -1,30 +1,30 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||||
Proc-Type: 4,ENCRYPTED
|
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIY7PpABd5xsYCAggA
|
||||||
DEK-Info: DES-EDE3-CBC,B9C24663685D6009
|
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
|
XwiQ2Rt3JBHrzPy9wXL8hw==
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END ENCRYPTED PRIVATE KEY-----
|
||||||
|
Binary file not shown.
@ -1,45 +1,45 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDvTCCAqWgAwIBAgIUSXAaPeUatfheDTFo77LnMBHgyeMwDQYJKoZIhvcNAQEL
|
MIIDvTCCAqWgAwIBAgIUazbrVgbYb+IN803UmJJa0DPHQsAwDQYJKoZIhvcNAQEL
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0yNDEyMzEwMDAwMDBaMG0xCzAJBgNVBAYT
|
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0zNDEyMzEwMDAwMDBaMG0xCzAJBgNVBAYT
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UE
|
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UE
|
||||||
AwwHUmV2b2tlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUu
|
AwwHUmV2b2tlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUu
|
||||||
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvripJQt3G9OnsDjZ
|
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx0EJrK233GytTHTY
|
||||||
2X8lsursYnhlw9u19TK9VMHla6e03TxumCfGWM43QiD2UWk3Y46Waz9Keh2UTpk7
|
V6Sr4iuxHZwLWkv00A03dNsG/xEq3Uh58yHxOMDW49o5hm/PejaaX2ooaYn67EeT
|
||||||
wZjyRi79orfMcgencTKTNE/WCV/u6RwIylxJpLlVSGjRBD09W+8wdU21pDTSvaLf
|
MuiMpuD3xtybEGuRZ6YtDCZG/WFkg7wPjGJhF3Q7QpmLOu/BbCU0APNddbDuLP4w
|
||||||
ibwNsaPhpFQ0jl4DpeXPPxCeG8KC1FNVunllGPGjVk2rZ4RnFrpScWyGXHqLT+iR
|
89aRePadPkyk5OLdLznVLA5z9z1JgJrMI/yswYi0ocs7uIKMrewXAEMj15pN3Y0S
|
||||||
g+t0pMi9S/bOhEV30f/v4HZfCx76qmlxl7QGIpJriXo+svaIe15gTb2CAstKp77N
|
OoQdp0jKYdGLN5M5pi/fgWiRCJGBH/OTh+VPr5voNAfGeVsiK9XrU4/hsGUW1deM
|
||||||
q8Y3sS/uM/5tktT/l6rnxIHLy4UEOSHUW9kQ8CcnZf+/A3PJKLopOWII9z0l/kbB
|
LiIZ0cshqGFUyXDqLEapHr3XSmwinRJPQozyXL437Ws+Gg2Q1IuqTMZS50qjuZW3
|
||||||
Imv7kwIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBRV5QgsukXk9bPmsAOJ
|
4KngQwIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBTprhNre3RQJMbThsJY
|
||||||
bNX/agQ/dTAfBgNVHSMEGDAWgBTj+r+NhAm1UfwIiw2e39lirWFyCzATBgNVHSUE
|
wKi0w8vJZTAfBgNVHSMEGDAWgBRkEPGrOTfcwf27Hcg/QVh3YifvKTATBgNVHSUE
|
||||||
DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAK/bCZPrxN+5HGQjZLIQg
|
DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAFJjwxpYA2jzrmF1mdKx/
|
||||||
jKfjTRL5xwBGs8+VW4i+xnaA14pyZjDlYzASmCE/ZiryVSMJ7fuQ0TVXGtz3N7PM
|
up8gl6iISsHDc7oLAv63oUYXpFwzpNfvi1TGqYVhntAH2t/1XdA1HKdBp2LDsEnt
|
||||||
v9pRgtcohs62NJZ5dIrq4f/Op1bii29pAA8+2EHPJUyFBt23vyvlI/dBpkgQG6mi
|
Av66c6HxyNPka26ZGD70+w5q8uHrIOO6MZw0eaLwu9bJI4cLbRXlKwxkGSzXHGYs
|
||||||
OUEsXQ+Q2LUD4OOJffkc/gowXcB4WFjrtFAUuu9HeZUNzV5Mm5FQTGm9nCnWsDIb
|
1hGR2YwAiMrqtVMPetlpd62y6qUZc0lEOhjJ6DsIfqSgO8AsdyI7Ao+cDqEZ1I/Q
|
||||||
b7Yx08hMy+6jtvkNPCDcFnos2bsipmVN4fCXkm5LPZNyMFoWReDbIKWASXaao2hN
|
Oi1Agn8kz8TtfWKxkX06EoL4DrZCDb1/w0CGQJATq77pKst+zw+B+2EKqlpuG3s/
|
||||||
gzWhwWsPlAGAlBPMVWEo3k2Cz/entbAijoyqS2koN4mZABy7m5+vfzFw/yvh1/lu
|
FE7RkCjG7bEFIDEK2909BXQNyQJzp7ih9X8QeEx5fnPr9lDfe/75YjRqoHkfmcTC
|
||||||
8w==
|
Hw==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDrDCCApSgAwIBAgIUXhcDbb/3vPpWoFCmesKw0dazbzIwDQYJKoZIhvcNAQEL
|
MIIDrDCCApSgAwIBAgIUcRGFYn4pUMRoDtFZhU1EOAPdiWwwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||||
AAOCAQ8AMIIBCgKCAQEA3FMSnznxLiZh2qZ2M4/Y3FcqzNy9XxE1DG5ahUoRifCe
|
AAOCAQ8AMIIBCgKCAQEA5yrw3i+fvxBSODvCoQb+9ibWRozmphJBp57tKv9ZraQ5
|
||||||
LWPGvREPG599ds55MesKqAPo1xAyd7hpQmd+IWzQhvDQntR4BkCQv6PoHQ2WO9co
|
THK+PkCdjNiJuxZn8F1QLsjJo6JqrrXufYln7wixK0Seu4uV6I2TRzcRyJx29D89
|
||||||
CfQ59U5h4pie82IROPHMg31PNYF7MVt2cjBtQco2wvL7XLroYo5nmi20qvsNh53S
|
0G9GrTXKn7v8z32QAqCgtwSZ17uWYTFmRAYPllWXcWDONsVyw3UF2nClndL7GMqM
|
||||||
nJ0vGsIhdBd5UVn7S5NghHYF03cmFiZVuSvN3ovFl1k0iIH+eJdfYXBiTqtcUCAc
|
gDizlwsfg8HmRpZegn82I7Y2DXccm9a7pFHuBHpwenKqfBnMsXo3Jj4Xlr1cLTrh
|
||||||
0+ngTui3LWd18QB6M6HYdT1a0MihGs1g0RE7ni2C5iwBn4FOe+eHzZOq5AcWVGR4
|
+6ksS5YogOsOd9b5Dfz6FaGmmwrlUWHwdi+EzdnSpOnXzmgflF23sZQ0ynsVvmpl
|
||||||
ZSvDc+6O22sy0esBYsPElJBnQLOPyIRwd4B8MO6PewIDAQABo2YwZDASBgNVHRMB
|
iD4rXBWnxnQ6Ken3wVPNrA/0ZYGbgSKrcv+/olkh5QIDAQABo2YwZDASBgNVHRMB
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBTj+r+NhAm1UfwIiw2e39lirWFyCzAfBgNV
|
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBRkEPGrOTfcwf27Hcg/QVh3YifvKTAfBgNV
|
||||||
HSMEGDAWgBRYinOUkj6959wnBw0YfDBGaz/adzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
HSMEGDAWgBQaPEb++qXSgmAi2vsewtpb6SiIyDAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
||||||
KoZIhvcNAQELBQADggEBACn3BOVCATol6TC31cKPvh9hOOq9uvgREGG1paTmZNhe
|
KoZIhvcNAQELBQADggEBAL22kK3SDGnr3lhRE7ipptlKalrQKfpght0XEKm5hxCL
|
||||||
JsrIUkD2KZN7dpAJEJF7uu2LaCm0F5VqQUj3SdYHD3neHiOeO8jzgM4BWgqZ3lZc
|
tougN2wtaTEWMwr2YfGJohcKBaGKQ+Bv6WY+EV+hJE4qEUFh6BGqRMtuZdiAbkG+
|
||||||
FQfGbNoR4QQMADMJYKJ/LCRjBKUrHDvkvuQHkb+y8yUg1UtNpeH3cFty2/eo7VWD
|
EveEMhZWQzgf9rUID+Y9Eg+NfCxlpkdQPjUxUV9OkGIshlxkUP8Y+C0h0xIcwq5v
|
||||||
Su5Jd1vVIo4XkQDBPr5UR9LVSMfhvhX4pcvijmETTEYn3ZZ2KeF1q5JC1Le+322Q
|
hAfNiJAdcw4fUvtLkpEOFoOjThB8zxOu+Cl3xLCcNOMPLdSxd3YXjy6CMuuOk4RB
|
||||||
xwgVhiJak3GUh06mYQf6qFSRanu78Jeyw8IlsS+o8V9W+dqYYDOENDYNJGB5MaS/
|
gOc8YCyyEvwb9KmARZpMOcQJmucMhs+aC3DF+n71g+agFhDl3Z0QkyyyRjAcD04+
|
||||||
yAA20r1RAb2RmPPbpiPjR2FKzNDxu7nHd4EecbSevdE=
|
sAR9C8PbqSCQAdydHbAFViEX6x3oGJ7L6zEDcIS10wg=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,46 +1,46 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIEDDCCAvSgAwIBAgIUMXc8FF4DEhJ/0czsG3SrcZS4GCYwDQYJKoZIhvcNAQEL
|
MIIEDDCCAvSgAwIBAgIUHGb2CHtm9Ra3gCn6Iv7hpEhiQrYwDQYJKoZIhvcNAQEL
|
||||||
BQAwZzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwZzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMMFkludGVybWVkaWF0
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNVBAMMFkludGVybWVkaWF0
|
||||||
ZSBDQSBDUkwgRFAwHhcNMTgwMTAxMDAwMDAwWhcNMjQxMjMxMDAwMDAwWjB7MQsw
|
ZSBDQSBDUkwgRFAwHhcNMTgwMTAxMDAwMDAwWhcNMzQxMjMxMDAwMDAwWjB7MQsw
|
||||||
CQYDVQQGEwJQTDEVMBMGA1UECgwMb3NzbHNpZ25jb2RlMQwwCgYDVQQLDANDU1Ax
|
CQYDVQQGEwJQTDEVMBMGA1UECgwMb3NzbHNpZ25jb2RlMQwwCgYDVQQLDANDU1Ax
|
||||||
HjAcBgNVBAMMFVJldm9rZWQgWDUwOXYzIENSTCBEUDEnMCUGCSqGSIb3DQEJARYY
|
HjAcBgNVBAMMFVJldm9rZWQgWDUwOXYzIENSTCBEUDEnMCUGCSqGSIb3DQEJARYY
|
||||||
b3NzbHNpZ25jb2RlQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
b3NzbHNpZ25jb2RlQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||||
MIIBCgKCAQEAvripJQt3G9OnsDjZ2X8lsursYnhlw9u19TK9VMHla6e03TxumCfG
|
MIIBCgKCAQEAx0EJrK233GytTHTYV6Sr4iuxHZwLWkv00A03dNsG/xEq3Uh58yHx
|
||||||
WM43QiD2UWk3Y46Waz9Keh2UTpk7wZjyRi79orfMcgencTKTNE/WCV/u6RwIylxJ
|
OMDW49o5hm/PejaaX2ooaYn67EeTMuiMpuD3xtybEGuRZ6YtDCZG/WFkg7wPjGJh
|
||||||
pLlVSGjRBD09W+8wdU21pDTSvaLfibwNsaPhpFQ0jl4DpeXPPxCeG8KC1FNVunll
|
F3Q7QpmLOu/BbCU0APNddbDuLP4w89aRePadPkyk5OLdLznVLA5z9z1JgJrMI/ys
|
||||||
GPGjVk2rZ4RnFrpScWyGXHqLT+iRg+t0pMi9S/bOhEV30f/v4HZfCx76qmlxl7QG
|
wYi0ocs7uIKMrewXAEMj15pN3Y0SOoQdp0jKYdGLN5M5pi/fgWiRCJGBH/OTh+VP
|
||||||
IpJriXo+svaIe15gTb2CAstKp77Nq8Y3sS/uM/5tktT/l6rnxIHLy4UEOSHUW9kQ
|
r5voNAfGeVsiK9XrU4/hsGUW1deMLiIZ0cshqGFUyXDqLEapHr3XSmwinRJPQozy
|
||||||
8CcnZf+/A3PJKLopOWII9z0l/kbBImv7kwIDAQABo4GbMIGYMAkGA1UdEwQCMAAw
|
XL437Ws+Gg2Q1IuqTMZS50qjuZW34KngQwIDAQABo4GbMIGYMAkGA1UdEwQCMAAw
|
||||||
HQYDVR0OBBYEFFXlCCy6ReT1s+awA4ls1f9qBD91MB8GA1UdIwQYMBaAFGG7QDpJ
|
HQYDVR0OBBYEFOmuE2t7dFAkxtOGwljAqLTDy8llMB8GA1UdIwQYMBaAFBQ8Yqni
|
||||||
x45ort5fDjQFGN/O5BYvMBMGA1UdJQQMMAoGCCsGAQUFBwMDMDYGA1UdHwQvMC0w
|
cYiW5meHqyh9KQSIau0jMBMGA1UdJQQMMAoGCCsGAQUFBwMDMDYGA1UdHwQvMC0w
|
||||||
K6ApoCeGJWh0dHA6Ly8xMjcuMC4wLjE6MTkyNTQvaW50ZXJtZWRpYXRlQ0EwDQYJ
|
K6ApoCeGJWh0dHA6Ly8xMjcuMC4wLjE6MTkyNTQvaW50ZXJtZWRpYXRlQ0EwDQYJ
|
||||||
KoZIhvcNAQELBQADggEBALwDivFFBjB7AkLO1jPJFyJnq8C0gadoYq0Dq5roAFMq
|
KoZIhvcNAQELBQADggEBAJ5WxnDiAiRPr7EvTRD7iaxixAY/2wgASXWekQLpvJ8Y
|
||||||
Lirl0LGsdFTrZ2ljKOzNrFVfw4EQHedDCsKCtsgOXG1xxLQczwsuBcIaWGzSdW15
|
/ehaVdZWE8ft76y73F4NC62JfjWgAZHE+we3LSO+eB5kznM+Ctzrf/brR1MorSOu
|
||||||
iNz+IKjHXSNOLEUvVcO6N6s1rt5U15lynaXFSdskBgJYA7vq6uA8RTWzhQC7aCv8
|
iq78uz2pjwmQBpby6uDMii9r1txR62GYiLrZJizE+13AOVKBo5EW0PuwX3wKjk+s
|
||||||
n3Tbpe8c7j6/y5NThffBu/YZypMoraZvPohCDfMZoFNT5GYXNWSeq7gipxtaCHcK
|
Z5Mp9y7+GVzCSXwJC4wNMw/ZJZgr+o5D8msMh3UPgxUfT1rZ7THW3IwXao3ZtTXw
|
||||||
OdWBi5yajIZL05hg29y7r677KBbvo07EykhxQ10zEnskzuqc7hCCsuDrXbmt5brv
|
EA6uJoLVNb8FLfAVA1CFL0MlPgyiM2iNs+jIuhF7hPmMc8Je2qAr97ADdLCHWnRv
|
||||||
REYpeGvJAu0YrFg9yLSl8FJwk/XUzGvxa2MLPyL/sj4=
|
Majsbns7OCCFROF2qSQiyzVO5Hn1kiPSP7qmLMak610=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIDszCCApugAwIBAgIUdUqeYLe6em9A4BIXcQhE2lS8KTUwDQYJKoZIhvcNAQEL
|
MIIDszCCApugAwIBAgIUN3RBnJCUJ8HmbeNjJZ/6jsXJLGEwDQYJKoZIhvcNAQEL
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBnMQswCQYDVQQGEwJQTDEVMBMG
|
MTgwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjBnMQswCQYDVQQGEwJQTDEVMBMG
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||||
cml0eTEfMB0GA1UEAwwWSW50ZXJtZWRpYXRlIENBIENSTCBEUDCCASIwDQYJKoZI
|
cml0eTEfMB0GA1UEAwwWSW50ZXJtZWRpYXRlIENBIENSTCBEUDCCASIwDQYJKoZI
|
||||||
hvcNAQEBBQADggEPADCCAQoCggEBANoHRxZ1qxQKLm8MLYswvTf9FBq05unFxE9j
|
hvcNAQEBBQADggEPADCCAQoCggEBAME32IBpxW4FhVuZe1PTarEskVHP233QjZtx
|
||||||
nea4njWqBkg3cT/jZo2sDHlkN+q3BFEL/K+mej0/LqfW6eXrskHj6OLyXas2/HR4
|
poC67/lUK44gtFmsxYsMrDYmmny5pfoM/Byxl5/rorEddLqtDe1kd1SpXUvEYxox
|
||||||
UYsby8djwazvt4LLiMS5yfo3GlRv5p44F1ruYu7/km7J/6pUxQMB+lTXKA4TzUWe
|
s5rizRd5sZPgkwNoJkSVyNZFwj7gKZHeg6IQHSxNgmTybZ+eZqiNvEveksj3lGpM
|
||||||
n/xa2xGm0ZDXvQC1GlPJ1mD/fm0JeS6g8iMdTfvKPKKFMArz+wGWBiqbAKnmuDfp
|
Xrbiew7cXUyIP636GPtYxLyIbwDVP0jScqcA/dmSAqofFVUi0SW3OS1hpyXAmmx8
|
||||||
J3j64nWyRCArH+tGgvOmqkXAUBh9A0T1AfdF1Q5kFKzFq38zKI6lPELo0qEio9SO
|
hQHJRKPjPgitZVgjwf5X8/eMTa+ca9dRlRFLk7AcbkF6NcbLm+cRo816nO0EBFV4
|
||||||
W+aOVVDtknTXmqKtawFyhn2e3UEzISYmFv2Wfc/dLnmBzRLNR9cCAwEAAaNmMGQw
|
Sn2dW9uYqJIfZcpRQ7wbv4fUCghwrk9h3gXrb7AweyK8nyYlmosCAwEAAaNmMGQw
|
||||||
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUYbtAOknHjmiu3l8ONAUY387k
|
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUFDxiqeJxiJbmZ4erKH0pBIhq
|
||||||
Fi8wHwYDVR0jBBgwFoAUWIpzlJI+vefcJwcNGHwwRms/2ncwDgYDVR0PAQH/BAQD
|
7SMwHwYDVR0jBBgwFoAUGjxG/vql0oJgItr7HsLaW+koiMgwDgYDVR0PAQH/BAQD
|
||||||
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQBJ69rsOHP4qKnu/wRS/D3fV/voLHB624Rg
|
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQAlI/1XnGc9WzL53rRascZc1EgWAnej9YFS
|
||||||
RpC4RshZMPVL60LaouJo1GMHj3IwyHVHGFkTxGYP0IIgcMUCnkmpSfX1tahYU+kB
|
Dax5+nozYTihC8BRxGfSh1FGRVsmFWhZ0z0XogJJC2bZrQ/36+vwoILItcsWHrQr
|
||||||
4fSCxheLg79g2y3Z1jTQxFOvRjn5t4BIk4Rq4o9E7n1x+8jcaCBSjmna9j6i5lgA
|
rFoZa6s1Uo7ZCd9SfmXjbhMLQgydocCh9YIF66CAkQLwRXc1QIpF7nuZ+rxk0ru1
|
||||||
QjazvdXrhhgrkvvMtk2wtk1laiHUHFgb9zxzNhhZFzy+QXwQv+Zj1N0swKfTP2gK
|
uGjjBrFRfdSdzlFnyK6wfFzi6LtYDVgVEHC7zzL9E/cyuGo7qQ++SoOg99HjTVY1
|
||||||
Rxls7e47SnMdvthINZpdvUwT5pBZnMKHqgQK6YbWcopBpuw7zOTJp6Ghqzqzwa4d
|
PS3ea522bRO2bJpYwZJvvbg020DAfm686VXwAadODdBkI2h6U5SwTxp4SkSmq9SI
|
||||||
CwUtEB7f0e7dWeG7DFJ2cNPcpXaigNtvfdRR3W1RduX9FCODihFF
|
mjtERFtnAKD0R2YrX4RzuIckezvwsqLDkQjMnI9XQmv5HWUZimcC
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,47 +1,47 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
JVHLUWz0r6IIp0mHrMwoI94yZBVXje0=
|
hpE0ajpKT0x/dNa/qCwl/9zc8XxGnPk=
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
0mCOiQ==
|
QepMyA==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1 +1 @@
|
|||||||
55c4d523e595564af0ab635fd1e3aaba
|
bb7fd13ddf056e0a3e621d3537b25478
|
||||||
|
@ -15,7 +15,7 @@ def main() -> None:
|
|||||||
try:
|
try:
|
||||||
with open(PORT_LOG, 'r') as file:
|
with open(PORT_LOG, 'r') as file:
|
||||||
port = file.readline()
|
port = file.readline()
|
||||||
conn = http.client.HTTPConnection('localhost', port)
|
conn = http.client.HTTPConnection('127.0.0.1', port)
|
||||||
conn.request('POST', '/kill_server')
|
conn.request('POST', '/kill_server')
|
||||||
response = conn.getresponse()
|
response = conn.getresponse()
|
||||||
print("HTTP status code:", response.getcode(), end=', ')
|
print("HTTP status code:", response.getcode(), end=', ')
|
||||||
|
@ -42,11 +42,11 @@ make_certs() {
|
|||||||
echo -n "$password" > tmp/password.txt
|
echo -n "$password" > tmp/password.txt
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Root CA certificate
|
# Root CA certificates
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
printf "\nGenerate root CA certificate\n" >> "makecerts.log"
|
printf "\nGenerate trusted root CA certificate\n" >> "makecerts.log"
|
||||||
"$OPENSSL" genrsa -out CA/CA.key \
|
"$OPENSSL" genrsa -out CA/CAroot.key \
|
||||||
2>> "makecerts.log" 1>&2
|
2>> "makecerts.log" 1>&2
|
||||||
test_result $?
|
test_result $?
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
||||||
@ -54,11 +54,48 @@ make_certs() {
|
|||||||
OPENSSL="$0"
|
OPENSSL="$0"
|
||||||
export LD_LIBRARY_PATH="$1"
|
export LD_LIBRARY_PATH="$1"
|
||||||
CONF="${script_path}/openssl_root.cnf"
|
CONF="${script_path}/openssl_root.cnf"
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 3600 -key CA/CA.key -out tmp/CACert.pem \
|
"$OPENSSL" req -config "$CONF" -new -x509 -days 7300 -key CA/CAroot.key -out tmp/CAroot.pem \
|
||||||
|
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Trusted Root CA" \
|
||||||
|
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
||||||
|
test_result $?
|
||||||
|
|
||||||
|
printf "\nPrepare the Certificate Signing Request (CSR)\n" >> "makecerts.log"
|
||||||
|
"$OPENSSL" genrsa -out CA/CA.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_root.cnf"
|
||||||
|
"$OPENSSL" req -config "$CONF" -new -key CA/CA.key -out CA/CACert.csr \
|
||||||
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Root CA" \
|
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Root CA" \
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
||||||
test_result $?
|
test_result $?
|
||||||
|
|
||||||
|
printf "\nGenerate Self-signed root CA certificate\n" >> "makecerts.log"
|
||||||
|
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" x509 -req -days 7300 -extfile "$CONF" -extensions ca_extensions \
|
||||||
|
-signkey CA/CA.key \
|
||||||
|
-in CA/CACert.csr -out tmp/CACert.pem \
|
||||||
|
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
||||||
|
test_result $?
|
||||||
|
|
||||||
|
printf "\nGenerate Cross-signed root CA certificate\n" >> "makecerts.log"
|
||||||
|
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_root.cnf"
|
||||||
|
"$OPENSSL" x509 -req -days 7300 -extfile "$CONF" -extensions ca_extensions \
|
||||||
|
-CA tmp/CAroot.pem -CAkey CA/CAroot.key -CAserial CA/CAroot.srl \
|
||||||
|
-CAcreateserial -in CA/CACert.csr -out tmp/CAcross.pem \
|
||||||
|
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
||||||
|
test_result $?
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Private RSA keys
|
# Private RSA keys
|
||||||
################################################################################
|
################################################################################
|
||||||
@ -146,19 +183,6 @@ make_certs() {
|
|||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
||||||
test_result $?
|
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"
|
printf "\nGenerate code signing certificate\n" >> "makecerts.log"
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/cert.csr \
|
"$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" \
|
-subj "/C=PL/ST=Mazovia Province/L=Warsaw/O=osslsigncode/OU=CSP/CN=Certificate/emailAddress=osslsigncode@example.com" \
|
||||||
@ -319,7 +343,7 @@ make_certs() {
|
|||||||
OPENSSL="$0"
|
OPENSSL="$0"
|
||||||
export LD_LIBRARY_PATH="$1"
|
export LD_LIBRARY_PATH="$1"
|
||||||
CONF="${script_path}/openssl_tsa_root.cnf"
|
CONF="${script_path}/openssl_tsa_root.cnf"
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 3600 -key CA/TSACA.key -out tmp/TSACA.pem \
|
"$OPENSSL" req -config "$CONF" -new -x509 -days 7300 -key CA/TSACA.key -out tmp/TSACA.pem \
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
||||||
test_result $?
|
test_result $?
|
||||||
|
|
||||||
@ -377,14 +401,14 @@ make_certs() {
|
|||||||
# Copy new files
|
# Copy new files
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
if test -s tmp/CACert.pem \
|
if test -s tmp/CACert.pem -a -s tmp/CAcross.pem -a -s tmp/CAroot.pem \
|
||||||
-a -s tmp/intermediateCA.pem -a -s tmp/intermediateCA_crldp.pem \
|
-a -s tmp/intermediateCA.pem -a -s tmp/intermediateCA_crldp.pem \
|
||||||
-a -s tmp/CACertCRL.pem -a -s tmp/CACertCRL.der \
|
-a -s tmp/CACertCRL.pem -a -s tmp/CACertCRL.der \
|
||||||
-a -s tmp/TSACertCRL.pem -a -s tmp/TSACertCRL.der \
|
-a -s tmp/TSACertCRL.pem -a -s tmp/TSACertCRL.der \
|
||||||
-a -s tmp/key.pem -a -s tmp/keyp.pem -a -s tmp/key.der -a -s tmp/key.pvk \
|
-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.der -a -s tmp/cert.spc \
|
-a -s tmp/cert.pem -a -s tmp/cert.der -a -s tmp/cert.spc \
|
||||||
-a -s tmp/cert.p12 -a -s tmp/legacy.p12 -a -s tmp/cert_crldp.pem\
|
-a -s tmp/cert.p12 -a -s tmp/legacy.p12 -a -s tmp/cert_crldp.pem\
|
||||||
-a -s tmp/crosscert.pem -a -s tmp/expired.pem \
|
-a -s tmp/expired.pem \
|
||||||
-a -s tmp/revoked.pem -a -s tmp/revoked_crldp.pem \
|
-a -s tmp/revoked.pem -a -s tmp/revoked_crldp.pem \
|
||||||
-a -s tmp/TSA_revoked.pem \
|
-a -s tmp/TSA_revoked.pem \
|
||||||
-a -s tmp/TSA.pem -a -s tmp/TSA.key -a -s tmp/tsa-chain.pem
|
-a -s tmp/TSA.pem -a -s tmp/TSA.key -a -s tmp/tsa-chain.pem
|
||||||
|
@ -20,8 +20,8 @@ crl_extensions = crl_ext
|
|||||||
default_md = sha256
|
default_md = sha256
|
||||||
preserve = no
|
preserve = no
|
||||||
policy = policy_loose
|
policy = policy_loose
|
||||||
default_startdate = 180101000000Z
|
default_startdate = 20180101000000Z
|
||||||
default_enddate = 241231000000Z
|
default_enddate = 20341231000000Z
|
||||||
x509_extensions = v3_req
|
x509_extensions = v3_req
|
||||||
email_in_dn = yes
|
email_in_dn = yes
|
||||||
default_days = 2200
|
default_days = 2200
|
||||||
|
@ -21,8 +21,8 @@ crl_extensions = crl_ext
|
|||||||
default_md = sha256
|
default_md = sha256
|
||||||
preserve = no
|
preserve = no
|
||||||
policy = policy_loose
|
policy = policy_loose
|
||||||
default_startdate = 180101000000Z
|
default_startdate = 20180101000000Z
|
||||||
default_enddate = 241231000000Z
|
default_enddate = 20341231000000Z
|
||||||
x509_extensions = v3_req
|
x509_extensions = v3_req
|
||||||
email_in_dn = yes
|
email_in_dn = yes
|
||||||
default_days = 2200
|
default_days = 2200
|
||||||
|
@ -18,8 +18,8 @@ crl_extensions = crl_ext
|
|||||||
default_md = sha256
|
default_md = sha256
|
||||||
preserve = no
|
preserve = no
|
||||||
policy = policy_match
|
policy = policy_match
|
||||||
default_startdate = 180101000000Z
|
default_startdate = 20180101000000Z
|
||||||
default_enddate = 260101000000Z
|
default_enddate = 20360101000000Z
|
||||||
x509_extensions = v3_intermediate_ca
|
x509_extensions = v3_intermediate_ca
|
||||||
email_in_dn = yes
|
email_in_dn = yes
|
||||||
default_days = 3000
|
default_days = 3000
|
||||||
|
@ -24,7 +24,7 @@ default_days = 3650
|
|||||||
default_crl_days = 365
|
default_crl_days = 365
|
||||||
policy = policy_match
|
policy = policy_match
|
||||||
default_startdate = 20180101000000Z
|
default_startdate = 20180101000000Z
|
||||||
default_enddate = 20280101000000Z
|
default_enddate = 20380101000000Z
|
||||||
unique_subject = no
|
unique_subject = no
|
||||||
email_in_dn = no
|
email_in_dn = no
|
||||||
x509_extensions = tsa_extensions
|
x509_extensions = tsa_extensions
|
||||||
|
0
tests/files/unsigned.256appx
Executable file → Normal file
0
tests/files/unsigned.256appx
Executable file → Normal file
0
tests/files/unsigned.512appx
Executable file → Normal file
0
tests/files/unsigned.512appx
Executable file → Normal file
Binary file not shown.
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>
|
@ -6,7 +6,8 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
from http.server import SimpleHTTPRequestHandler, HTTPServer
|
||||||
|
from socketserver import ThreadingMixIn
|
||||||
|
|
||||||
RESULT_PATH = os.getcwd()
|
RESULT_PATH = os.getcwd()
|
||||||
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
||||||
@ -27,6 +28,8 @@ OPENSSL_TS = ["openssl", "ts",
|
|||||||
"-queryfile", REQUEST,
|
"-queryfile", REQUEST,
|
||||||
"-out", RESPONS]
|
"-out", RESPONS]
|
||||||
|
|
||||||
|
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
|
daemon_threads = True
|
||||||
|
|
||||||
class RequestHandler(SimpleHTTPRequestHandler):
|
class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
"""Handle the HTTP POST request that arrive at the server"""
|
"""Handle the HTTP POST request that arrive at the server"""
|
||||||
@ -43,6 +46,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
|||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header("Content-type", "application/crl")
|
self.send_header("Content-type", "application/crl")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
# Read the file and send the contents
|
# Read the file and send the contents
|
||||||
if url.path == "/intermediateCA":
|
if url.path == "/intermediateCA":
|
||||||
with open(CACRL, 'rb') as file:
|
with open(CACRL, 'rb') as file:
|
||||||
@ -52,7 +56,8 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
|||||||
resp_data = file.read()
|
resp_data = file.read()
|
||||||
self.wfile.write(resp_data)
|
self.wfile.write(resp_data)
|
||||||
except Exception as err: # pylint: disable=broad-except
|
except Exception as err: # pylint: disable=broad-except
|
||||||
print(f"HTTP GET request error: {err}")
|
print("HTTP GET request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
def do_POST(self): # pylint: disable=invalid-name
|
def do_POST(self): # pylint: disable=invalid-name
|
||||||
""""Serves the POST request type"""
|
""""Serves the POST request type"""
|
||||||
@ -76,12 +81,12 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
|||||||
openssl.check_returncode()
|
openssl.check_returncode()
|
||||||
self.send_header("Content-type", "application/timestamp-reply")
|
self.send_header("Content-type", "application/timestamp-reply")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
resp_data = None
|
resp_data = b''
|
||||||
with open(RESPONS, mode="rb") as file:
|
with open(RESPONS, mode="rb") as file:
|
||||||
resp_data = file.read()
|
resp_data = file.read()
|
||||||
self.wfile.write(resp_data)
|
self.wfile.write(resp_data)
|
||||||
except Exception as err: # pylint: disable=broad-except
|
except Exception as err: # pylint: disable=broad-except
|
||||||
print(f"HTTP POST request error: {err}")
|
print("HTTP POST request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
class HttpServerThread():
|
class HttpServerThread():
|
||||||
@ -93,12 +98,12 @@ class HttpServerThread():
|
|||||||
self.server_thread = None
|
self.server_thread = None
|
||||||
|
|
||||||
def start_server(self, port) -> (int):
|
def start_server(self, port) -> (int):
|
||||||
"""Starting HTTP server on localhost and a random available port for binding"""
|
"""Starting HTTP server on 127.0.0.1 and a random available port for binding"""
|
||||||
self.server = ThreadingHTTPServer(('localhost', port), RequestHandler)
|
self.server = ThreadingHTTPServer(('127.0.0.1', port), RequestHandler)
|
||||||
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
||||||
self.server_thread.start()
|
self.server_thread.start()
|
||||||
hostname, port = self.server.server_address[:2]
|
hostname, port = self.server.server_address[:2]
|
||||||
print(f"HTTP server started, URL http://{hostname}:{port}")
|
print("HTTP server started, URL http://{}:{}".format(hostname, port))
|
||||||
return port
|
return port
|
||||||
|
|
||||||
|
|
||||||
@ -119,7 +124,7 @@ def main() -> None:
|
|||||||
with open(PORT_LOG, mode="w") as file:
|
with open(PORT_LOG, mode="w") as file:
|
||||||
file.write("{}".format(port))
|
file.write("{}".format(port))
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
print(f"OSError: {err}")
|
print("OSError: {}".format(err))
|
||||||
ret = err.errno
|
ret = err.errno
|
||||||
finally:
|
finally:
|
||||||
sys.exit(ret)
|
sys.exit(ret)
|
||||||
@ -131,7 +136,7 @@ if __name__ == '__main__':
|
|||||||
if fpid > 0:
|
if fpid > 0:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except OSError as ferr:
|
except OSError as ferr:
|
||||||
print(f"Fork #1 failed: {ferr.errno} {ferr.strerror}")
|
print("Fork #1 failed: {} {}".format(ferr.errno, ferr.strerror))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -139,7 +144,7 @@ if __name__ == '__main__':
|
|||||||
if fpid > 0:
|
if fpid > 0:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except OSError as ferr:
|
except OSError as ferr:
|
||||||
print(f"Fork #2 failed: {ferr.errno} {ferr.strerror}")
|
print("Fork #2 failed: {} {}".format(ferr.errno, ferr.strerror))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Start the daemon main loop
|
# Start the daemon main loop
|
||||||
|
@ -43,6 +43,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
|||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header("Content-type", "application/crl")
|
self.send_header("Content-type", "application/crl")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
# Read the file and send the contents
|
# Read the file and send the contents
|
||||||
if url.path == "/intermediateCA":
|
if url.path == "/intermediateCA":
|
||||||
with open(CACRL, 'rb') as file:
|
with open(CACRL, 'rb') as file:
|
||||||
@ -52,7 +53,8 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
|||||||
resp_data = file.read()
|
resp_data = file.read()
|
||||||
self.wfile.write(resp_data)
|
self.wfile.write(resp_data)
|
||||||
except Exception as err: # pylint: disable=broad-except
|
except Exception as err: # pylint: disable=broad-except
|
||||||
print(f"HTTP GET request error: {err}")
|
print("HTTP GET request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
def do_POST(self): # pylint: disable=invalid-name
|
def do_POST(self): # pylint: disable=invalid-name
|
||||||
""""Serves the POST request type"""
|
""""Serves the POST request type"""
|
||||||
@ -76,12 +78,12 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
|||||||
openssl.check_returncode()
|
openssl.check_returncode()
|
||||||
self.send_header("Content-type", "application/timestamp-reply")
|
self.send_header("Content-type", "application/timestamp-reply")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
resp_data = None
|
resp_data = b''
|
||||||
with open(RESPONS, mode="rb") as file:
|
with open(RESPONS, mode="rb") as file:
|
||||||
resp_data = file.read()
|
resp_data = file.read()
|
||||||
self.wfile.write(resp_data)
|
self.wfile.write(resp_data)
|
||||||
except Exception as err: # pylint: disable=broad-except
|
except Exception as err: # pylint: disable=broad-except
|
||||||
print(f"HTTP POST request error: {err}")
|
print("HTTP POST request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
class HttpServerThread():
|
class HttpServerThread():
|
||||||
@ -93,12 +95,12 @@ class HttpServerThread():
|
|||||||
self.server_thread = None
|
self.server_thread = None
|
||||||
|
|
||||||
def start_server(self) -> (int):
|
def start_server(self) -> (int):
|
||||||
"""Starting HTTP server on localhost and a random available port for binding"""
|
"""Starting HTTP server on 127.0.0.1 and a random available port for binding"""
|
||||||
self.server = ThreadingHTTPServer(('localhost', 19254), RequestHandler)
|
self.server = ThreadingHTTPServer(('127.0.0.1', 19254), RequestHandler)
|
||||||
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
||||||
self.server_thread.start()
|
self.server_thread.start()
|
||||||
hostname, port = self.server.server_address[:2]
|
hostname, port = self.server.server_address[:2]
|
||||||
print(f"HTTP server started, URL http://{hostname}:{port}")
|
print("HTTP server started, URL http://{}:{}".format(hostname, port))
|
||||||
return port
|
return port
|
||||||
|
|
||||||
|
|
||||||
@ -113,7 +115,7 @@ def main() -> None:
|
|||||||
with open(PORT_LOG, mode="w") as file:
|
with open(PORT_LOG, mode="w") as file:
|
||||||
file.write("{}".format(port))
|
file.write("{}".format(port))
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
print(f"OSError: {err}")
|
print("OSError: {}".format(err))
|
||||||
ret = err.errno
|
ret = err.errno
|
||||||
finally:
|
finally:
|
||||||
sys.exit(ret)
|
sys.exit(ret)
|
||||||
|
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.
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
|
@ -8,5 +8,6 @@
|
|||||||
"name": "python3",
|
"name": "python3",
|
||||||
"platform": "!(windows & static) & !osx"
|
"platform": "!(windows & static) & !osx"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"builtin-baseline": "9edb1b8e590cc086563301d735cae4b6e732d2d2"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user