Initial commit.
This commit is contained in:
commit
00bd137586
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/bin
|
||||||
|
/deps/**/*
|
||||||
|
/obj
|
||||||
|
/src/.magic.h
|
121
LICENSE.txt
Normal file
121
LICENSE.txt
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
Creative Commons Legal Code
|
||||||
|
|
||||||
|
CC0 1.0 Universal
|
||||||
|
|
||||||
|
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||||
|
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||||
|
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||||
|
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||||
|
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||||
|
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||||
|
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||||
|
HEREUNDER.
|
||||||
|
|
||||||
|
Statement of Purpose
|
||||||
|
|
||||||
|
The laws of most jurisdictions throughout the world automatically confer
|
||||||
|
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||||
|
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||||
|
authorship and/or a database (each, a "Work").
|
||||||
|
|
||||||
|
Certain owners wish to permanently relinquish those rights to a Work for
|
||||||
|
the purpose of contributing to a commons of creative, cultural and
|
||||||
|
scientific works ("Commons") that the public can reliably and without fear
|
||||||
|
of later claims of infringement build upon, modify, incorporate in other
|
||||||
|
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||||
|
and for any purposes, including without limitation commercial purposes.
|
||||||
|
These owners may contribute to the Commons to promote the ideal of a free
|
||||||
|
culture and the further production of creative, cultural and scientific
|
||||||
|
works, or to gain reputation or greater distribution for their Work in
|
||||||
|
part through the use and efforts of others.
|
||||||
|
|
||||||
|
For these and/or other purposes and motivations, and without any
|
||||||
|
expectation of additional consideration or compensation, the person
|
||||||
|
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||||
|
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||||
|
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||||
|
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||||
|
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||||
|
|
||||||
|
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||||
|
protected by copyright and related or neighboring rights ("Copyright and
|
||||||
|
Related Rights"). Copyright and Related Rights include, but are not
|
||||||
|
limited to, the following:
|
||||||
|
|
||||||
|
i. the right to reproduce, adapt, distribute, perform, display,
|
||||||
|
communicate, and translate a Work;
|
||||||
|
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||||
|
iii. publicity and privacy rights pertaining to a person's image or
|
||||||
|
likeness depicted in a Work;
|
||||||
|
iv. rights protecting against unfair competition in regards to a Work,
|
||||||
|
subject to the limitations in paragraph 4(a), below;
|
||||||
|
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||||
|
in a Work;
|
||||||
|
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||||
|
European Parliament and of the Council of 11 March 1996 on the legal
|
||||||
|
protection of databases, and under any national implementation
|
||||||
|
thereof, including any amended or successor version of such
|
||||||
|
directive); and
|
||||||
|
vii. other similar, equivalent or corresponding rights throughout the
|
||||||
|
world based on applicable law or treaty, and any national
|
||||||
|
implementations thereof.
|
||||||
|
|
||||||
|
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||||
|
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||||
|
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||||
|
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||||
|
of action, whether now known or unknown (including existing as well as
|
||||||
|
future claims and causes of action), in the Work (i) in all territories
|
||||||
|
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||||
|
treaty (including future time extensions), (iii) in any current or future
|
||||||
|
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||||
|
including without limitation commercial, advertising or promotional
|
||||||
|
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||||
|
member of the public at large and to the detriment of Affirmer's heirs and
|
||||||
|
successors, fully intending that such Waiver shall not be subject to
|
||||||
|
revocation, rescission, cancellation, termination, or any other legal or
|
||||||
|
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||||
|
as contemplated by Affirmer's express Statement of Purpose.
|
||||||
|
|
||||||
|
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||||
|
be judged legally invalid or ineffective under applicable law, then the
|
||||||
|
Waiver shall be preserved to the maximum extent permitted taking into
|
||||||
|
account Affirmer's express Statement of Purpose. In addition, to the
|
||||||
|
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||||
|
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||||
|
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||||
|
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||||
|
maximum duration provided by applicable law or treaty (including future
|
||||||
|
time extensions), (iii) in any current or future medium and for any number
|
||||||
|
of copies, and (iv) for any purpose whatsoever, including without
|
||||||
|
limitation commercial, advertising or promotional purposes (the
|
||||||
|
"License"). The License shall be deemed effective as of the date CC0 was
|
||||||
|
applied by Affirmer to the Work. Should any part of the License for any
|
||||||
|
reason be judged legally invalid or ineffective under applicable law, such
|
||||||
|
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||||
|
of the License, and in such case Affirmer hereby affirms that he or she
|
||||||
|
will not (i) exercise any of his or her remaining Copyright and Related
|
||||||
|
Rights in the Work or (ii) assert any associated claims and causes of
|
||||||
|
action with respect to the Work, in either case contrary to Affirmer's
|
||||||
|
express Statement of Purpose.
|
||||||
|
|
||||||
|
4. Limitations and Disclaimers.
|
||||||
|
|
||||||
|
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||||
|
surrendered, licensed or otherwise affected by this document.
|
||||||
|
b. Affirmer offers the Work as-is and makes no representations or
|
||||||
|
warranties of any kind concerning the Work, express, implied,
|
||||||
|
statutory or otherwise, including without limitation warranties of
|
||||||
|
title, merchantability, fitness for a particular purpose, non
|
||||||
|
infringement, or the absence of latent or other defects, accuracy, or
|
||||||
|
the present or absence of errors, whether or not discoverable, all to
|
||||||
|
the greatest extent permissible under applicable law.
|
||||||
|
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||||
|
that may apply to the Work or any use thereof, including without
|
||||||
|
limitation any person's Copyright and Related Rights in the Work.
|
||||||
|
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||||
|
consents, permissions or other rights required for any use of the
|
||||||
|
Work.
|
||||||
|
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||||
|
party to this document and has no duty or obligation with respect to
|
||||||
|
this CC0 or use of the Work.
|
66
Makefile
Normal file
66
Makefile
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# FLAGS
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MACHINE := $(shell gcc -dumpmachine)
|
||||||
|
ifeq ($(MACHINE),$(filter x86_64-%,$(MACHINE)))
|
||||||
|
MYCPU := x64
|
||||||
|
MARCH := x86-64
|
||||||
|
MTUNE := corei7
|
||||||
|
else
|
||||||
|
MYCPU := x86
|
||||||
|
MARCH := i486
|
||||||
|
MTUNE := intel
|
||||||
|
endif
|
||||||
|
|
||||||
|
CFLAGS = -municode -march=$(MARCH) -mtune=$(MTUNE) -Os -DNDEBUG -Wall -flto -Ideps/$(MYCPU)/include
|
||||||
|
LDFLAGS = -static -Ldeps/$(MYCPU)/lib -Wl,--strip-all
|
||||||
|
LIBS = -lcrypto
|
||||||
|
|
||||||
|
ifneq ($(XCFLAGS),)
|
||||||
|
CFLAGS += $(XCFLAGS)
|
||||||
|
endif
|
||||||
|
ifneq ($(XLDFLAGS),)
|
||||||
|
LDFLAGS += $(XLDFLAGS)
|
||||||
|
endif
|
||||||
|
ifneq ($(XLIBS),)
|
||||||
|
LIBS += $(XLIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# RULES
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.PHONY: all keygen sign verify subdirs clean
|
||||||
|
|
||||||
|
all: keygen sign verify
|
||||||
|
|
||||||
|
keygen: subdirs src/.magic.h
|
||||||
|
windres -DAPP="Key Generator ($(MYCPU))" -DNAME=keygen -o obj/version_keygen.o res/version.rc
|
||||||
|
gcc $(CFLAGS) $(LDFLAGS) -o bin/codesign_keygen.exe src/codesign_keygen.c src/common.c obj/version_keygen.o $(LIBS)
|
||||||
|
|
||||||
|
sign: subdirs src/.magic.h
|
||||||
|
windres -DAPP="Signer ($(MYCPU))" -DNAME=sign -o obj/version_sign.o res/version.rc
|
||||||
|
gcc $(CFLAGS) $(LDFLAGS) -o bin/codesign_sign.exe src/codesign_sign.c src/common.c obj/version_sign.o $(LIBS)
|
||||||
|
|
||||||
|
verify: subdirs src/.magic.h
|
||||||
|
windres -DAPP="Verifier ($(MYCPU))" -DNAME=verify -o obj/version_verify.o res/version.rc
|
||||||
|
windres -DAPP="Verifier ($(MYCPU))" -DNAME=verifz -o obj/version_verifz.o res/version.rc
|
||||||
|
gcc $(CFLAGS) -UEMBED_PUBKEY $(LDFLAGS) -o bin/codesign_verify.exe src/codesign_verify.c src/common.c obj/version_verify.o $(LIBS)
|
||||||
|
gcc $(CFLAGS) -DEMBED_PUBKEY $(LDFLAGS) -o bin/codesign_verifz.exe src/codesign_verify.c src/common.c obj/version_verifz.o $(LIBS)
|
||||||
|
|
||||||
|
src/.magic.h:
|
||||||
|
str=$$(tr -dc '0-9A-F' < /dev/urandom | head -c 26); \
|
||||||
|
printf 'static const unsigned char MAGIC_NMBR[] = { ' > $@; \
|
||||||
|
for i in {0..12}; do \
|
||||||
|
[ $$i -gt 0 ] && printf ', '; \
|
||||||
|
printf '0x%s' $${str:((2*i)):2}; \
|
||||||
|
done >> $@; \
|
||||||
|
printf ' };\n' >> $@
|
||||||
|
|
||||||
|
subdirs:
|
||||||
|
@mkdir -p bin obj
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf bin obj
|
||||||
|
rm -f src/.magic.h
|
51
deps/build-openssl.sh
vendored
Normal file
51
deps/build-openssl.sh
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
trap 'read -p "Press any key..." x' EXIT
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# Set up compiler
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
case "$(cc -dumpmachine)" in
|
||||||
|
i686-*)
|
||||||
|
readonly MY_CPU=x86
|
||||||
|
readonly MY_MARCH=i486
|
||||||
|
readonly MY_MTUNE=intel
|
||||||
|
;;
|
||||||
|
x86_64-*)
|
||||||
|
readonly MY_CPU=x64
|
||||||
|
readonly MY_MARCH=x86-64
|
||||||
|
readonly MY_MTUNE=corei7
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown compiler detected!";
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# Initialize paths
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
readonly BASE_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
|
||||||
|
readonly LIBS_DIR="${BASE_DIR}/${MY_CPU}"
|
||||||
|
readonly OSSL_DIR="${LIBS_DIR}/.build/openssl"
|
||||||
|
find "${BASE_DIR}" -maxdepth 1 -type d -name "*-${MY_CPU}" -exec rm -rf "{}" \;
|
||||||
|
rm -rf "${LIBS_DIR}" && mkdir -p "${LIBS_DIR}/bin" "${LIBS_DIR}/include" "${LIBS_DIR}/lib/pkgconfig" "${LIBS_DIR}/share" "${OSSL_DIR}"
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# Fetch sources
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
wget -4 -O "${LIBS_DIR}/openssl.tar.gz" https://www.openssl.org/source/openssl-1.1.1k.tar.gz
|
||||||
|
tar -xvf "${LIBS_DIR}/openssl.tar.gz" --strip-components=1 -C "${OSSL_DIR}"
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# Build
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
[[ "${MY_CPU}" == "x64" ]] && readonly ossl_flag="no-sse2" || readonly ossl_flag="386"
|
||||||
|
[[ "${MY_CPU}" == "x64" ]] && readonly ossl_mngw="mingw64" || readonly ossl_mngw="mingw"
|
||||||
|
pushd "${OSSL_DIR}"
|
||||||
|
./Configure no-afalgeng no-aria no-asan no-asm no-async no-autoerrinit no-autoload-config no-bf no-blake2 no-buildtest-c++ no-camellia no-capieng no-cast no-chacha no-cmac no-cms no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-ct no-deprecated no-des no-devcryptoeng no-dgram no-dh no-dsa no-dso no-dtls no-dynamic-engine no-ec no-ec2m no-ecdh no-ecdsa no-ec_nistp_64_gcc_128 no-egd no-engine no-err no-external-tests no-filenames no-fuzz-libfuzzer no-fuzz-afl no-gost no-heartbeats no-hw no-idea no-makedepend no-md2 no-md4 no-mdc2 no-msan no-multiblock no-nextprotoneg no-pinshared no-ocb no-ocsp no-pic no-poly1305 no-posix-io no-psk no-rc2 no-rc4 no-rc5 no-rdrand no-rfc3779 no-rmd160 no-scrypt no-sctp no-seed no-shared no-siphash no-sm2 no-sm3 no-sm4 no-sock no-srp no-srtp no-ssl no-ssl-trace no-static-engine no-tests no-threads no-tls no-ts no-ubsan no-ui-console no-unit-test no-whirlpool no-weak-ssl-ciphers no-zlib no-zlib-dynamic ${ossl_flag} -static -march=${MY_MARCH} -mtune=${MY_MTUNE} -Os -flto -D_WIN32_WINNT=0x0501 -I"${LIBS_DIR}/include" -L"${LIBS_DIR}/lib" --prefix="${LIBS_DIR}" ${ossl_mngw}
|
||||||
|
make build_libs && make install_dev
|
||||||
|
popd
|
||||||
|
|
||||||
|
printf "\nCompleted.\n\n"
|
63
res/version.rc
Normal file
63
res/version.rc
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#include "WinResrc.h" //"afxres.h"
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
#define VERSION_MAJOR 1
|
||||||
|
#define VERSION_MINOR 0
|
||||||
|
#define VERSION_PATCH 0
|
||||||
|
#define VERSION_BUILD 0
|
||||||
|
|
||||||
|
#define _T(X) #X
|
||||||
|
#define T(X) _T(X)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Neutral resources
|
||||||
|
//
|
||||||
|
#ifdef _WIN32
|
||||||
|
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
|
#pragma code_page(1252)
|
||||||
|
#endif //_WIN32
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_BUILD
|
||||||
|
PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_BUILD
|
||||||
|
FILEFLAGSMASK 0x17L
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x3L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x2L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "000004b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "ProductName", "CodeSign"
|
||||||
|
VALUE "FileDescription", "CodeSign - " T(APP)
|
||||||
|
VALUE "ProductVersion", T(VERSION_MAJOR) "." T(VERSION_MINOR) "." T(VERSION_PATCH)
|
||||||
|
VALUE "FileVersion", T(VERSION_MAJOR) "." T(VERSION_MINOR) "." T(VERSION_PATCH)
|
||||||
|
VALUE "InternalName", "codesign_" T(NAME)
|
||||||
|
VALUE "OriginalFilename", "codesign_" T(NAME) ".exe"
|
||||||
|
VALUE "LegalCopyright", "Created by LoRd_MuldeR <MuldeR2@GMX.de>"
|
||||||
|
VALUE "CompanyName", "Muldersoft"
|
||||||
|
VALUE "LegalTrademarks", "Muldersoft"
|
||||||
|
VALUE "Comments", "This work has been released under the CC0 1.0 Universal license!"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x0, 1200
|
||||||
|
END
|
||||||
|
END
|
195
src/codesign_keygen.c
Normal file
195
src/codesign_keygen.c
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* CodeSign, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <share.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#define RSA_EXPONENT 0x10001
|
||||||
|
#define RSA_KEY_SIZE 8192
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t *argv[])
|
||||||
|
{
|
||||||
|
int exit_code = EXIT_FAILURE;
|
||||||
|
BIGNUM *exp = NULL;
|
||||||
|
RSA *rsa = NULL;
|
||||||
|
FILE *file_pubkey = NULL, *file_privkey = NULL;
|
||||||
|
const EVP_CIPHER *enc = NULL;
|
||||||
|
char *passwd = NULL;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Check arguments */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
print_logo("Sign Tool");
|
||||||
|
|
||||||
|
if ((argc < 4) || (!argv[1][0]) || (!argv[2][0]) || (!argv[3][0]))
|
||||||
|
{
|
||||||
|
print_license();
|
||||||
|
fputs("Usage:\n", stderr);
|
||||||
|
fputs(" codesign_keygen.exe <passwd> <signkey.pub> <signkey.key>\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Open output files */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
file_pubkey = _wfsopen(argv[2], L"wb", _SH_DENYRW);
|
||||||
|
if (!file_pubkey)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open output file for public key!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_privkey = _wfsopen(argv[3], L"wb", _SH_DENYRW);
|
||||||
|
if (!file_privkey)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open output file for private key!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Read password */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
if ((argv[1][0] == L'-') && (argv[1][1] == L'\0'))
|
||||||
|
{
|
||||||
|
passwd = read_line_from_file(stdin, 0);
|
||||||
|
if (!passwd)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to read password from STDIN stream!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
passwd = convert_wchar_to_UTF8(argv[1]);
|
||||||
|
if (!passwd)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to convert password to UTF-8 format!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(passwd) < PASSWD_MINLEN)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: Password is too short! (min. length: %d)\n\n", PASSWD_MINLEN);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Generate RSA key-pair */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
exp = BN_new();
|
||||||
|
if (!exp)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to allocate exponent!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BN_set_word(exp, RSA_EXPONENT) != 1)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to set up exponent!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsa = RSA_new();
|
||||||
|
if (!rsa)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to allocate RSA context!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("Generating RSA key-pair. Please be patient, this will take a while...\n", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
if (RSA_generate_key_ex(rsa, RSA_KEY_SIZE, exp, NULL) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to generate RAS key!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("Completed.\n\n", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Write public and private keys to files */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
enc = EVP_aes_256_cbc();
|
||||||
|
if (!enc)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to initialize cipher for key export!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PEM_write_RSAPublicKey(file_pubkey, rsa) != 1)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to write the public key file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force_flush(file_pubkey))
|
||||||
|
{
|
||||||
|
fputs("I/O Error: Public key could not be written completely!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PEM_write_RSAPrivateKey(file_privkey, rsa, enc, (unsigned char*)passwd, strlen(passwd), NULL, NULL) != 1)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to write the private key file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force_flush(file_privkey))
|
||||||
|
{
|
||||||
|
fputs("I/O Error: Private key could not be written completely!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("RSA key-pair written successfully.\n\n", stderr);
|
||||||
|
exit_code = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Final clean-up */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
clean_up:
|
||||||
|
|
||||||
|
if (passwd)
|
||||||
|
{
|
||||||
|
zero_memory(passwd, _msize(passwd));
|
||||||
|
free(passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_pubkey)
|
||||||
|
{
|
||||||
|
fclose(file_pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_privkey)
|
||||||
|
{
|
||||||
|
fclose(file_privkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsa)
|
||||||
|
{
|
||||||
|
RSA_free(rsa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp)
|
||||||
|
{
|
||||||
|
BN_free(exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
260
src/codesign_sign.c
Normal file
260
src/codesign_sign.c
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* CodeSign, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include ".magic.h"
|
||||||
|
|
||||||
|
#include <share.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#define BUFFSIZE 4096
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t *argv[])
|
||||||
|
{
|
||||||
|
int exit_code = EXIT_FAILURE;
|
||||||
|
RSA *rsa = NULL;
|
||||||
|
SHA512_CTX sha512 = { };
|
||||||
|
FILE *file_privkey = NULL, *file_data = NULL, *file_signature = NULL;
|
||||||
|
char *passwd = NULL, *base64 = NULL;
|
||||||
|
unsigned char buffer[BUFFSIZE], digest[SHA512_DIGEST_LENGTH], timestamp[sizeof(UI64_T)], *output = NULL;
|
||||||
|
unsigned int signature_length = 0U, output_length = 0U, base64_length = 0U;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Check arguments */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
print_logo("Signer");
|
||||||
|
|
||||||
|
if ((argc < 5) || (!argv[1][0]) || (!argv[2][0]) || (!argv[3][0]) || (!argv[4][0]))
|
||||||
|
{
|
||||||
|
print_license();
|
||||||
|
fputs("Usage:\n", stderr);
|
||||||
|
fputs(" codesign_sign.exe <passwd> <signkey.key> <filename.dat> <signature.sig>\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Open input/output files */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
file_privkey = _wfsopen(argv[2], L"rb", _SH_DENYWR);
|
||||||
|
if (!file_privkey)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open private key file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_data = _wfsopen(argv[3], L"rb", _SH_DENYWR);
|
||||||
|
if (!file_data)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open input file to be signed!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_signature = _wfsopen(argv[4], L"wb", _SH_DENYRW);
|
||||||
|
if (!file_signature)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open output file for signature!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Read password */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
if ((argv[1][0] == L'-') && (argv[1][1] == L'\0'))
|
||||||
|
{
|
||||||
|
passwd = read_line_from_file(stdin, 0);
|
||||||
|
if (!passwd)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to read password from STDIN stream!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
passwd = convert_wchar_to_UTF8(argv[1]);
|
||||||
|
if (!passwd)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to convert password to UTF-8 format!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(passwd) < PASSWD_MINLEN)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: Password is too short! (min. length: %d)\n\n", PASSWD_MINLEN);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Read the private key */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
if (!PEM_read_RSAPrivateKey(file_privkey, &rsa, NULL, passwd))
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to read the private key! Wrong password?\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
store_uint64(timestamp, get_current_time());
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Compute file digest */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
if (SHA512_Init(&sha512) != 1)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to initialize SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("Generating the RSA signature, please wait...\n", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
if (SHA512_Update(&sha512, timestamp, sizeof(timestamp)) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(feof(file_data) || ferror(file_data)))
|
||||||
|
{
|
||||||
|
const size_t count = fread(buffer, sizeof(unsigned char), BUFFSIZE, file_data);
|
||||||
|
if (count > 0U)
|
||||||
|
{
|
||||||
|
if (SHA512_Update(&sha512, buffer, count) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ferror(file_data))
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nI/O Error: Failed to read input file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SHA512_Update(&sha512, MAGIC_NMBR, sizeof(MAGIC_NMBR)) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SHA512_Final(digest, &sha512) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to finalize SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Compute the RSA signature */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
output = (unsigned char*) malloc(RSA_size(rsa) + sizeof(timestamp));
|
||||||
|
if (!output)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to allocate output buffer!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(output, timestamp, sizeof(timestamp));
|
||||||
|
|
||||||
|
if (RSA_sign(NID_sha512, digest, SHA512_DIGEST_LENGTH, output + sizeof(timestamp), &signature_length, rsa) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to compute signature!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("Completed.\n\n", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Write signature the output file */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
base64 = (char*) malloc(1U + (base64_length = 4U * (((output_length = signature_length + sizeof(timestamp)) + 2U) / 3U)));
|
||||||
|
if (!base64)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to allocate hex-string buffer!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_EncodeBlock((unsigned char*)base64, output, output_length) != base64_length)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to encode signature to Base64!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite(base64, sizeof(char), base64_length, file_signature) != base64_length)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to write signature to output file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!force_flush(file_signature))
|
||||||
|
{
|
||||||
|
fputs("I/O Error: Signature could not be written completely!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("RSA signature written successfully.\n\n", stderr);
|
||||||
|
exit_code = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Final clean-up */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
clean_up:
|
||||||
|
|
||||||
|
if (passwd)
|
||||||
|
{
|
||||||
|
zero_memory(passwd, strlen(passwd));
|
||||||
|
free(passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base64)
|
||||||
|
{
|
||||||
|
zero_memory(base64, strlen(base64));
|
||||||
|
free(base64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
zero_memory(output, _msize(output));
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_privkey)
|
||||||
|
{
|
||||||
|
fclose(file_privkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_data)
|
||||||
|
{
|
||||||
|
fclose(file_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_signature)
|
||||||
|
{
|
||||||
|
fclose(file_signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsa)
|
||||||
|
{
|
||||||
|
RSA_free(rsa);
|
||||||
|
}
|
||||||
|
|
||||||
|
zero_memory(timestamp, sizeof(timestamp));
|
||||||
|
zero_memory(&sha512, sizeof(SHA512_CTX));
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
320
src/codesign_verify.c
Normal file
320
src/codesign_verify.c
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* CodeSign, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include ".magic.h"
|
||||||
|
|
||||||
|
#include <share.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
#ifdef EMBED_PUBKEY
|
||||||
|
#define ARGV_INPUTFILE argv[1]
|
||||||
|
#define ARGV_SIGNATURE argv[2]
|
||||||
|
#else
|
||||||
|
#define ARGV_INPUTFILE argv[2]
|
||||||
|
#define ARGV_SIGNATURE argv[3]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUFFSIZE 4096
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t *argv[])
|
||||||
|
{
|
||||||
|
int exit_code = EXIT_FAILURE;
|
||||||
|
BIO *bio_pubkey = NULL;
|
||||||
|
RSA *rsa = NULL;
|
||||||
|
SHA512_CTX sha512 = { };
|
||||||
|
char *base64 = NULL;
|
||||||
|
FILE *file_pubkey = NULL, *file_data = NULL, *file_signature = NULL;
|
||||||
|
UI64_T timestamp = 0U, current_time = 0U;
|
||||||
|
unsigned char buffer[BUFFSIZE], digest[SHA512_DIGEST_LENGTH], *input = NULL;
|
||||||
|
unsigned int input_length = 0U, base64_length = 0U;
|
||||||
|
#ifdef EMBED_PUBKEY
|
||||||
|
const unsigned char *public_key = NULL, *checksum_pubkey = NULL;
|
||||||
|
unsigned int pubkey_length = 0U, checksum_length = 0U;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Check arguments */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
print_logo("Verifier");
|
||||||
|
|
||||||
|
#ifdef EMBED_PUBKEY
|
||||||
|
|
||||||
|
if ((argc < 3) || (!argv[1][0]) || (!argv[2][0]))
|
||||||
|
{
|
||||||
|
print_license();
|
||||||
|
fputs("Usage:\n", stderr);
|
||||||
|
fputs(" codesign_verify.exe <filename.dat> <signature.sig>\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
if ((argc < 4) || (!argv[1][0]) || (!argv[2][0]) || (!argv[3][0]))
|
||||||
|
{
|
||||||
|
print_license();
|
||||||
|
fputs("Usage:\n", stderr);
|
||||||
|
fputs(" codesign_verify.exe <signkey.pub> <filename.dat> <signature.sig>\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Load the public key */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef EMBED_PUBKEY
|
||||||
|
|
||||||
|
public_key = load_resource_data(L"RSA_PUBLIC_KEY", &pubkey_length);
|
||||||
|
if (!public_key)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to load public key data from resources!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
checksum_pubkey = load_resource_data(L"CHECKSUM_SHA512", &checksum_length);
|
||||||
|
if ((!checksum_pubkey) || (checksum_length < SHA512_DIGEST_LENGTH))
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to load public key checksum from resources!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SHA512(public_key, pubkey_length, digest))
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to compute checksum of the public key!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(digest, checksum_pubkey, SHA512_DIGEST_LENGTH) != 0)
|
||||||
|
{
|
||||||
|
fputs("Error: Public key checksum does not match the expected value!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
bio_pubkey = BIO_new_mem_buf(public_key, pubkey_length);
|
||||||
|
if (!bio_pubkey)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to allocate memory BIO for public key!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PEM_read_bio_RSAPublicKey(bio_pubkey, &rsa, NULL, NULL))
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to read the public key from memory!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
file_pubkey = _wfsopen(argv[1], L"rb", _SH_DENYWR);
|
||||||
|
if (!file_pubkey)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open public key input file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PEM_read_RSAPublicKey(file_pubkey, &rsa, NULL, NULL))
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to read the public key from file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Open input files */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
file_data = _wfsopen(ARGV_INPUTFILE, L"rb", _SH_DENYWR);
|
||||||
|
if (!file_data)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open the input file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_signature = _wfsopen(ARGV_SIGNATURE, L"rb", _SH_DENYWR);
|
||||||
|
if (!file_signature)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to open the signature file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
base64 = read_line_from_file(file_signature, 1);
|
||||||
|
if (!base64)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to read the signature from file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((base64_length = strlen(base64)) < 4U)
|
||||||
|
{
|
||||||
|
fputs("Error: The signature appears to be incomplete!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Decode signature input data */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
input = (unsigned char*) malloc(1U + (3U * ((base64_length + 3U) / 4U)));
|
||||||
|
if (!input)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to allocate the input buffer!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_length = EVP_DecodeBlock(input, (unsigned char*)base64, base64_length);
|
||||||
|
if ((int)input_length <= 0)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to decode signature data from Base64 format!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_length <= 2U + sizeof(UI64_T))
|
||||||
|
{
|
||||||
|
fputs("Error: Signature binary data appears to be truncated!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base64[base64_length - 1U] == '=')
|
||||||
|
{
|
||||||
|
input_length -= (base64[base64_length - 2U] == '=') ? 2U : 1U; /*remove padding!*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Check the time-stamp */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
timestamp = load_uint64(input);
|
||||||
|
|
||||||
|
if (timestamp > (current_time = get_current_time()))
|
||||||
|
{
|
||||||
|
fputs("Error: Signature time-stamp appears to be from the future!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_time - timestamp > 94670856000000ULL)
|
||||||
|
{
|
||||||
|
fputs("Error: Signature time-stamp is more than 3 years old!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Compute file digest */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
if (SHA512_Init(&sha512) != 1)
|
||||||
|
{
|
||||||
|
fputs("Error: Failed to initialize SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("Verifying the RSA signature, please wait...\n", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
if (SHA512_Update(&sha512, input, sizeof(UI64_T)) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(feof(file_data) || ferror(file_data)))
|
||||||
|
{
|
||||||
|
const size_t count = fread(buffer, sizeof(unsigned char), BUFFSIZE, file_data);
|
||||||
|
if (count > 0U)
|
||||||
|
{
|
||||||
|
if (SHA512_Update(&sha512, buffer, count) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ferror(file_data))
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nI/O Error: Failed to read input file!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SHA512_Update(&sha512, MAGIC_NMBR, sizeof(MAGIC_NMBR)) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SHA512_Final(digest, &sha512) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nError: Failed to finalize SHA-512 digest!\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Validate the RSA signature */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
if (RSA_verify(NID_sha512, digest, SHA512_DIGEST_LENGTH, input + sizeof(UI64_T), input_length - sizeof(UI64_T), rsa) != 1)
|
||||||
|
{
|
||||||
|
fputs("Failed!\n\nInvalid signature or corrupted file :-(\n\n", stderr);
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("Completed.\n\nThe signature is valid :-)\n\n", stderr);
|
||||||
|
exit_code = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
/* Final clean-up */
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
|
||||||
|
clean_up:
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
{
|
||||||
|
zero_memory(input, _msize(input));
|
||||||
|
free(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base64)
|
||||||
|
{
|
||||||
|
zero_memory(base64, strlen(base64));
|
||||||
|
free(base64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_pubkey)
|
||||||
|
{
|
||||||
|
fclose(file_pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_data)
|
||||||
|
{
|
||||||
|
fclose(file_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_signature)
|
||||||
|
{
|
||||||
|
fclose(file_signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bio_pubkey)
|
||||||
|
{
|
||||||
|
BIO_free(bio_pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsa)
|
||||||
|
{
|
||||||
|
RSA_free(rsa);
|
||||||
|
}
|
||||||
|
|
||||||
|
zero_memory(&sha512, sizeof(SHA512_CTX));
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
162
src/common.c
Normal file
162
src/common.c
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* CodeSign, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
|
void print_logo(const char *const app_name)
|
||||||
|
{
|
||||||
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
||||||
|
_setmode(_fileno(stdin), _O_BINARY);
|
||||||
|
fprintf(stderr, "CodeSign - %s [" __DATE__ "], by LoRd_MuldeR <mulder2@gmx.de>\n", app_name);
|
||||||
|
fprintf(stderr, "using %.15s\n\n", OpenSSL_version(OPENSSL_VERSION));
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_license(void)
|
||||||
|
{
|
||||||
|
fputs("This work has been released under the CC0 1.0 Universal license!\n", stderr);
|
||||||
|
fputs("Please see http://www.muldersoft.com for additional information.\n\n", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *convert_wchar_to_UTF8(const wchar_t *str_w)
|
||||||
|
{
|
||||||
|
char *str_utf8 = NULL;
|
||||||
|
if (str_w)
|
||||||
|
{
|
||||||
|
int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (bytes > 0)
|
||||||
|
{
|
||||||
|
str_utf8 = malloc(bytes);
|
||||||
|
if(str_utf8)
|
||||||
|
{
|
||||||
|
if (WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes, NULL, NULL) == 0)
|
||||||
|
{
|
||||||
|
free(str_utf8);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str_utf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *read_line_from_file(FILE *const file, const int trim)
|
||||||
|
{
|
||||||
|
char buffer[4096], *line;
|
||||||
|
size_t len;
|
||||||
|
while(!(feof(file) || ferror(file)))
|
||||||
|
{
|
||||||
|
if((line = fgets(buffer, sizeof(buffer), file)))
|
||||||
|
{
|
||||||
|
if (trim)
|
||||||
|
{
|
||||||
|
while (*line && isspace(*line))
|
||||||
|
{
|
||||||
|
++line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = strlen(line);
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
if ((line[len - 1U] != '\r') && (line[len - 1U] != '\n'))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line[--len] = '\0';
|
||||||
|
}
|
||||||
|
if (trim)
|
||||||
|
{
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
if (!isspace(line[len - 1U]))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line[--len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
return strdup(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI64_T get_current_time(void)
|
||||||
|
{
|
||||||
|
struct timeval t;
|
||||||
|
if(gettimeofday(&t, NULL) == 0)
|
||||||
|
{
|
||||||
|
return (((UI64_T)t.tv_sec) * 1000000ULL) + ((UI64_T)t.tv_usec);
|
||||||
|
}
|
||||||
|
return 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_uint64(unsigned char *const buffer, const UI64_T value)
|
||||||
|
{
|
||||||
|
buffer[0U] = (BYTE)(value >> 56);
|
||||||
|
buffer[1U] = (BYTE)(value >> 48);
|
||||||
|
buffer[2U] = (BYTE)(value >> 40);
|
||||||
|
buffer[3U] = (BYTE)(value >> 32);
|
||||||
|
buffer[4U] = (BYTE)(value >> 24);
|
||||||
|
buffer[5U] = (BYTE)(value >> 16);
|
||||||
|
buffer[6U] = (BYTE)(value >> 8);
|
||||||
|
buffer[7U] = (BYTE)(value >> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
UI64_T load_uint64(const unsigned char *const buffer)
|
||||||
|
{
|
||||||
|
UI64_T value = 0U;
|
||||||
|
value |= ((UI64_T)buffer[0U]) << 56;
|
||||||
|
value |= ((UI64_T)buffer[1U]) << 48;
|
||||||
|
value |= ((UI64_T)buffer[2U]) << 40;
|
||||||
|
value |= ((UI64_T)buffer[3U]) << 32;
|
||||||
|
value |= ((UI64_T)buffer[4U]) << 24;
|
||||||
|
value |= ((UI64_T)buffer[5U]) << 16;
|
||||||
|
value |= ((UI64_T)buffer[6U]) << 8;
|
||||||
|
value |= ((UI64_T)buffer[7U]) << 0;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char* load_resource_data(const wchar_t *const name, unsigned int *const length)
|
||||||
|
{
|
||||||
|
HRSRC resource = FindResourceW(NULL, name, RT_RCDATA);
|
||||||
|
if (resource)
|
||||||
|
{
|
||||||
|
*length = SizeofResource(NULL, resource);
|
||||||
|
if (*length > 0U)
|
||||||
|
{
|
||||||
|
HGLOBAL data = LoadResource(NULL, resource);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
return (const unsigned char*) LockResource(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*length = 0U;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int force_flush(FILE *const file)
|
||||||
|
{
|
||||||
|
const int result = fflush(file);
|
||||||
|
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(file)));
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zero_memory(void *const ptr, const size_t size)
|
||||||
|
{
|
||||||
|
SecureZeroMemory(ptr, size);
|
||||||
|
}
|
26
src/common.h
Normal file
26
src/common.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* CodeSign, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _COMMON_H
|
||||||
|
#define _COMMON_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define PASSWD_MINLEN 8
|
||||||
|
typedef unsigned long long UI64_T;
|
||||||
|
|
||||||
|
void print_logo(const char *const app_name);
|
||||||
|
void print_license(void);
|
||||||
|
char *convert_wchar_to_UTF8(const wchar_t *str_w);
|
||||||
|
char *read_line_from_file(FILE *const file, const int trim);
|
||||||
|
UI64_T get_current_time(void);
|
||||||
|
void store_uint64(unsigned char *const buffer, const UI64_T value);
|
||||||
|
UI64_T load_uint64(const unsigned char *const buffer);
|
||||||
|
const unsigned char* load_resource_data(const wchar_t *const name, unsigned int *const length);
|
||||||
|
int force_flush(FILE *const file);
|
||||||
|
void zero_memory(void *const ptr, const size_t size);
|
||||||
|
|
||||||
|
#endif /*_COMMON_H*/
|
Loading…
Reference in New Issue
Block a user