diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6bd1aae --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +Makefile text eol=lf +*.sh text eol=lf diff --git a/.gitignore b/.gitignore index 28ad3d6..f290326 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ /deps/**/* /obj /src/.magic.h +/utilities/PasswordDialog/.vs +/utilities/PasswordDialog/bin +/utilities/PasswordDialog/obj diff --git a/Makefile b/Makefile index e193634..0af502e 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +SHELL := bash + # --------------------------------------------------------------------------- # FLAGS # --------------------------------------------------------------------------- @@ -13,10 +15,15 @@ else MTUNE := intel endif -CFLAGS = -municode -march=$(MARCH) -mtune=$(MTUNE) -Os -DNDEBUG -Wall -flto -Ideps/$(MYCPU)/include -LDFLAGS = -static -Ldeps/$(MYCPU)/lib -Wl,--strip-all +CFLAGS = -march=$(MARCH) -mtune=$(MTUNE) -Os -DNDEBUG -Wall -flto -Ideps/$(MYCPU)/include +LDFLAGS = -Ldeps/$(MYCPU)/lib -static -Wl,--strip-all LIBS = -lcrypto +ifeq ($(MACHINE),$(filter %-mingw32,$(MACHINE))) + SUFFIX = .exe + LDFLAGS += -municode +endif + ifneq ($(XCFLAGS),) CFLAGS += $(XCFLAGS) endif @@ -35,19 +42,15 @@ endif 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) +keygen: subdirs src/.magic.h rsrc + gcc $(CFLAGS) $(LDFLAGS) -o bin/codesign_keygen$(SUFFIX) 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) + gcc $(CFLAGS) $(LDFLAGS) -o bin/codesign_sign$(SUFFIX) 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) +verify: subdirs src/.magic.h rsrc + gcc $(CFLAGS) -UEMBED_PUBKEY $(LDFLAGS) -o bin/codesign_verify$(SUFFIX) src/codesign_verify.c src/common.c obj/version_verify.o $(LIBS) + gcc $(CFLAGS) -DEMBED_PUBKEY $(LDFLAGS) -o bin/codesign_verifz$(SUFFIX) src/codesign_verify.c src/common.c obj/version_verify.o $(LIBS) src/.magic.h: str=$$(tr -dc '0-9A-F' < /dev/urandom | head -c 26); \ @@ -58,7 +61,18 @@ src/.magic.h: done >> $@; \ printf ' };\n' >> $@ -subdirs: +rsrc: subdirs +ifeq ($(MACHINE),$(filter %-mingw32,$(MACHINE))) + windres -DAPP="Key Generator ($(MYCPU))" -DNAME=keygen -o obj/version_keygen.o res/version.rc + windres -DAPP="Signer ($(MYCPU))" -DNAME=sign -o obj/version_sign.o res/version.rc + windres -DAPP="Verifier ($(MYCPU))" -DNAME=verify -o obj/version_verify.o res/version.rc +else + gcc -o obj/version_keygen.o -xc -c - < /dev/null + gcc -o obj/version_sign.o -xc -c - < /dev/null + gcc -o obj/version_verify.o -xc -c - < /dev/null +endif + +subdirs: deps/$(MYCPU)/lib/libcrypto.a deps/$(MYCPU)/lib/libssl.a @mkdir -p bin obj clean: diff --git a/deps/build-openssl-linux.sh b/deps/build-openssl-linux.sh new file mode 100644 index 0000000..85bdb9e --- /dev/null +++ b/deps/build-openssl-linux.sh @@ -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_linux="linux-x86_64" || readonly ossl_linux="linux-x86" +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_linux} +make build_libs && make install_dev +popd + +printf "\nCompleted.\n\n" diff --git a/deps/build-openssl.sh b/deps/build-openssl-mingw.sh similarity index 100% rename from deps/build-openssl.sh rename to deps/build-openssl-mingw.sh diff --git a/src/codesign_keygen.c b/src/codesign_keygen.c index eb076f6..d8c2a51 100644 --- a/src/codesign_keygen.c +++ b/src/codesign_keygen.c @@ -4,7 +4,6 @@ /******************************************************************************/ #include "common.h" -#include #include #include @@ -15,7 +14,7 @@ #define RSA_EXPONENT 0x10001 #define RSA_KEY_SIZE 8192 -int wmain(int argc, wchar_t *argv[]) +int MAIN(int argc, CHAR_T *argv[]) { int exit_code = EXIT_FAILURE; BIGNUM *exp = NULL; @@ -28,7 +27,7 @@ int wmain(int argc, wchar_t *argv[]) /* Check arguments */ /*-------------------------------------------------------*/ - print_logo("Sign Tool"); + print_logo("Key Generator"); if ((argc < 4) || (!argv[1][0]) || (!argv[2][0]) || (!argv[3][0])) { @@ -42,14 +41,14 @@ int wmain(int argc, wchar_t *argv[]) /* Open output files */ /*-------------------------------------------------------*/ - file_pubkey = _wfsopen(argv[2], L"wb", _SH_DENYRW); + file_pubkey = FOPEN(argv[2], T("wb")); 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); + file_privkey = FOPEN(argv[3], T("wb")); if (!file_privkey) { fputs("Error: Failed to open output file for private key!\n\n", stderr); @@ -71,7 +70,7 @@ int wmain(int argc, wchar_t *argv[]) } else { - passwd = convert_wchar_to_UTF8(argv[1]); + passwd = convert_CHAR_to_UTF8(argv[1]); if (!passwd) { fputs("Error: Failed to convert password to UTF-8 format!\n\n", stderr); @@ -167,7 +166,7 @@ clean_up: if (passwd) { - zero_memory(passwd, _msize(passwd)); + OPENSSL_cleanse(passwd, strlen(passwd)); free(passwd); } diff --git a/src/codesign_sign.c b/src/codesign_sign.c index a8b1c41..c7e0a93 100644 --- a/src/codesign_sign.c +++ b/src/codesign_sign.c @@ -6,7 +6,6 @@ #include "common.h" #include ".magic.h" -#include #include #include @@ -15,21 +14,22 @@ #define BUFFSIZE 4096 -int wmain(int argc, wchar_t *argv[]) +int MAIN(int argc, CHAR_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; + uint64_t timestamp = 0ULL; + unsigned char buffer[BUFFSIZE], digest[SHA512_DIGEST_LENGTH], ts_buffer[sizeof(uint64_t)], *output = NULL; unsigned int signature_length = 0U, output_length = 0U, base64_length = 0U; /*-------------------------------------------------------*/ /* Check arguments */ /*-------------------------------------------------------*/ - print_logo("Signer"); + print_logo("File Signer"); if ((argc < 5) || (!argv[1][0]) || (!argv[2][0]) || (!argv[3][0]) || (!argv[4][0])) { @@ -43,21 +43,21 @@ int wmain(int argc, wchar_t *argv[]) /* Open input/output files */ /*-------------------------------------------------------*/ - file_privkey = _wfsopen(argv[2], L"rb", _SH_DENYWR); + file_privkey = FOPEN(argv[2], T("rb")); 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); + file_data = FOPEN(argv[3], T("rb")); 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); + file_signature = FOPEN(argv[4], T("wb")); if (!file_signature) { fputs("Error: Failed to open output file for signature!\n\n", stderr); @@ -79,7 +79,7 @@ int wmain(int argc, wchar_t *argv[]) } else { - passwd = convert_wchar_to_UTF8(argv[1]); + passwd = convert_CHAR_to_UTF8(argv[1]); if (!passwd) { fputs("Error: Failed to convert password to UTF-8 format!\n\n", stderr); @@ -103,7 +103,18 @@ int wmain(int argc, wchar_t *argv[]) goto clean_up; } - store_uint64(timestamp, get_current_time()); + /*-------------------------------------------------------*/ + /* Get current time */ + /*-------------------------------------------------------*/ + + timestamp = get_current_time_usec(); + if (!(timestamp > 0ULL)) + { + fputs("Error: Failed to get the current system time!\n\n", stderr); + goto clean_up; + } + + store_uint64(ts_buffer, timestamp); /*-------------------------------------------------------*/ /* Compute file digest */ @@ -118,7 +129,7 @@ int wmain(int argc, wchar_t *argv[]) fputs("Generating the RSA signature, please wait...\n", stderr); fflush(stderr); - if (SHA512_Update(&sha512, timestamp, sizeof(timestamp)) != 1) + if (SHA512_Update(&sha512, ts_buffer, sizeof(ts_buffer)) != 1) { fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr); goto clean_up; @@ -159,16 +170,16 @@ int wmain(int argc, wchar_t *argv[]) /* Compute the RSA signature */ /*-------------------------------------------------------*/ - output = (unsigned char*) malloc(RSA_size(rsa) + sizeof(timestamp)); + output = (unsigned char*) malloc(RSA_size(rsa) + sizeof(ts_buffer)); if (!output) { fputs("Failed!\n\nError: Failed to allocate output buffer!\n\n", stderr); goto clean_up; } - memcpy(output, timestamp, sizeof(timestamp)); + memcpy(output, ts_buffer, sizeof(ts_buffer)); - if (RSA_sign(NID_sha512, digest, SHA512_DIGEST_LENGTH, output + sizeof(timestamp), &signature_length, rsa) != 1) + if (RSA_sign(NID_sha512, digest, SHA512_DIGEST_LENGTH, output + sizeof(ts_buffer), &signature_length, rsa) != 1) { fputs("Failed!\n\nError: Failed to compute signature!\n\n", stderr); goto clean_up; @@ -181,7 +192,7 @@ int wmain(int argc, wchar_t *argv[]) /* Write signature the output file */ /*-------------------------------------------------------*/ - base64 = (char*) malloc(1U + (base64_length = 4U * (((output_length = signature_length + sizeof(timestamp)) + 2U) / 3U))); + base64 = (char*) malloc(1U + (base64_length = 4U * (((output_length = signature_length + sizeof(ts_buffer)) + 2U) / 3U))); if (!base64) { fputs("Error: Failed to allocate hex-string buffer!\n\n", stderr); @@ -217,19 +228,19 @@ clean_up: if (passwd) { - zero_memory(passwd, strlen(passwd)); + OPENSSL_cleanse(passwd, strlen(passwd)); free(passwd); } if (base64) { - zero_memory(base64, strlen(base64)); + OPENSSL_cleanse(base64, strlen(base64)); free(base64); } if (output) { - zero_memory(output, _msize(output)); + OPENSSL_cleanse(output, MSIZE(output)); free(output); } @@ -253,8 +264,10 @@ clean_up: RSA_free(rsa); } - zero_memory(timestamp, sizeof(timestamp)); - zero_memory(&sha512, sizeof(SHA512_CTX)); + + OPENSSL_cleanse(ts_buffer, sizeof(ts_buffer)); + OPENSSL_cleanse(&sha512, sizeof(SHA512_CTX)); + OPENSSL_cleanse(×tamp, sizeof(uint64_t)); return exit_code; } diff --git a/src/codesign_verify.c b/src/codesign_verify.c index c07c735..19ddc4b 100644 --- a/src/codesign_verify.c +++ b/src/codesign_verify.c @@ -6,7 +6,6 @@ #include "common.h" #include ".magic.h" -#include #include #include @@ -24,7 +23,7 @@ #define BUFFSIZE 4096 -int wmain(int argc, wchar_t *argv[]) +int MAIN(int argc, CHAR_T *argv[]) { int exit_code = EXIT_FAILURE; BIO *bio_pubkey = NULL; @@ -32,7 +31,6 @@ int wmain(int argc, wchar_t *argv[]) 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 @@ -44,7 +42,7 @@ int wmain(int argc, wchar_t *argv[]) /* Check arguments */ /*-------------------------------------------------------*/ - print_logo("Verifier"); + print_logo("File Verifier"); #ifdef EMBED_PUBKEY @@ -74,14 +72,14 @@ int wmain(int argc, wchar_t *argv[]) #ifdef EMBED_PUBKEY - public_key = load_resource_data(L"RSA_PUBLIC_KEY", &pubkey_length); + public_key = load_resource_data(T("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); + checksum_pubkey = load_resource_data(T("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); @@ -115,7 +113,7 @@ int wmain(int argc, wchar_t *argv[]) #else - file_pubkey = _wfsopen(argv[1], L"rb", _SH_DENYWR); + file_pubkey = FOPEN(argv[1], T("rb")); if (!file_pubkey) { fputs("Error: Failed to open public key input file!\n\n", stderr); @@ -134,14 +132,14 @@ int wmain(int argc, wchar_t *argv[]) /* Open input files */ /*-------------------------------------------------------*/ - file_data = _wfsopen(ARGV_INPUTFILE, L"rb", _SH_DENYWR); + file_data = FOPEN(ARGV_INPUTFILE, T("rb")); 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); + file_signature = FOPEN(ARGV_SIGNATURE, T("rb")); if (!file_signature) { fputs("Error: Failed to open the signature file!\n\n", stderr); @@ -179,7 +177,7 @@ int wmain(int argc, wchar_t *argv[]) goto clean_up; } - if (input_length <= 2U + sizeof(UI64_T)) + if (input_length <= 2U + sizeof(uint64_t)) { fputs("Error: Signature binary data appears to be truncated!\n\n", stderr); goto clean_up; @@ -190,24 +188,6 @@ int wmain(int argc, wchar_t *argv[]) 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 */ /*-------------------------------------------------------*/ @@ -221,7 +201,7 @@ int wmain(int argc, wchar_t *argv[]) fputs("Verifying the RSA signature, please wait...\n", stderr); fflush(stderr); - if (SHA512_Update(&sha512, input, sizeof(UI64_T)) != 1) + if (SHA512_Update(&sha512, input, sizeof(uint64_t)) != 1) { fputs("Failed!\n\nError: Failed to update SHA-512 digest!\n\n", stderr); goto clean_up; @@ -262,7 +242,7 @@ int wmain(int argc, wchar_t *argv[]) /* Validate the RSA signature */ /*-------------------------------------------------------*/ - if (RSA_verify(NID_sha512, digest, SHA512_DIGEST_LENGTH, input + sizeof(UI64_T), input_length - sizeof(UI64_T), rsa) != 1) + if (RSA_verify(NID_sha512, digest, SHA512_DIGEST_LENGTH, input + sizeof(uint64_t), input_length - sizeof(uint64_t), rsa) != 1) { fputs("Failed!\n\nInvalid signature or corrupted file :-(\n\n", stderr); goto clean_up; @@ -279,13 +259,13 @@ clean_up: if (input) { - zero_memory(input, _msize(input)); + OPENSSL_cleanse(input, MSIZE(input)); free(input); } if (base64) { - zero_memory(base64, strlen(base64)); + OPENSSL_cleanse(base64, strlen(base64)); free(base64); } @@ -314,7 +294,7 @@ clean_up: RSA_free(rsa); } - zero_memory(&sha512, sizeof(SHA512_CTX)); + OPENSSL_cleanse(&sha512, sizeof(SHA512_CTX)); return exit_code; } diff --git a/src/common.c b/src/common.c index 0e6fc44..4e711ea 100644 --- a/src/common.c +++ b/src/common.c @@ -4,19 +4,31 @@ /******************************************************************************/ #include "common.h" -#include -#include -#include +#include +#include +#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN 1 #include +#include +#include +#else +#include +#include +#endif #include +/*-------------------------------------------------------*/ +/* print_logo() / print_license() */ +/*-------------------------------------------------------*/ + void print_logo(const char *const app_name) { +#ifdef _WIN32 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); _setmode(_fileno(stdin), _O_BINARY); +#endif fprintf(stderr, "CodeSign - %s [" __DATE__ "], by LoRd_MuldeR \n", app_name); fprintf(stderr, "using %.15s\n\n", OpenSSL_version(OPENSSL_VERSION)); fflush(stderr); @@ -28,18 +40,23 @@ void print_license(void) fputs("Please see http://www.muldersoft.com for additional information.\n\n", stderr); } -char *convert_wchar_to_UTF8(const wchar_t *str_w) +/*-------------------------------------------------------*/ +/* convert_wchar_to_UTF8() */ +/*-------------------------------------------------------*/ + +char *convert_CHAR_to_UTF8(const CHAR_T *str) { char *str_utf8 = NULL; - if (str_w) +#ifdef _WIN32 + if (str) { - int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, 0, NULL, NULL); + int bytes = WideCharToMultiByte(CP_UTF8, 0, str, -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) + if (WideCharToMultiByte(CP_UTF8, 0, str, -1, str_utf8, bytes, NULL, NULL) == 0) { free(str_utf8); return NULL; @@ -47,9 +64,16 @@ char *convert_wchar_to_UTF8(const wchar_t *str_w) } } } +#else + str_utf8 = strdup(str); +#endif return str_utf8; } +/*-------------------------------------------------------*/ +/* read_line_from_file() */ +/*-------------------------------------------------------*/ + char *read_line_from_file(FILE *const file, const int trim) { char buffer[4096], *line; @@ -94,44 +118,94 @@ char *read_line_from_file(FILE *const file, const int trim) return NULL; } -UI64_T get_current_time(void) +/*-------------------------------------------------------*/ +/* get_current_time() */ +/*-------------------------------------------------------*/ + +#define FILETIME_1970 116444736000000000ULL + +#ifdef _WIN32 + +static inline uint64_t filetime_to_ui64(const FILETIME *const file_time) { - struct timeval t; + ULARGE_INTEGER result; + result.HighPart = file_time->dwHighDateTime; + result. LowPart = file_time-> dwLowDateTime; + return result.QuadPart; +} + +static uint64_t get_system_time(void) +{ + FILETIME system_time; + GetSystemTimeAsFileTime(&system_time); + return filetime_to_ui64(&system_time); +} + +uint64_t get_current_time_usec(void) +{ + /* struct timeval t; if(gettimeofday(&t, NULL) == 0) { - return (((UI64_T)t.tv_sec) * 1000000ULL) + ((UI64_T)t.tv_usec); + return (((uint64_t)t.tv_sec) * 1000000ULL) + ((uint64_t)t.tv_usec); + } */ + const uint64_t system_time = get_system_time(); + if (system_time >= FILETIME_1970) + { + return (system_time - FILETIME_1970) / 10ULL; } return 0ULL; } -void store_uint64(unsigned char *const buffer, const UI64_T value) +#else + +uint64_t get_current_time_usec(void) { - 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); + struct timeval t; + if(gettimeofday(&t, NULL) == 0) + { + return (((uint64_t)t.tv_sec) * 1000000ULL) + ((uint64_t)t.tv_usec); + } + return 0ULL; } -UI64_T load_uint64(const unsigned char *const buffer) +#endif + +/*-------------------------------------------------------*/ +/* store_uint64() / load_uint64() */ +/*-------------------------------------------------------*/ + +void store_uint64(unsigned char *const buffer, const uint64_t value) { - 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; + buffer[0U] = (uint8_t)(value >> 56); + buffer[1U] = (uint8_t)(value >> 48); + buffer[2U] = (uint8_t)(value >> 40); + buffer[3U] = (uint8_t)(value >> 32); + buffer[4U] = (uint8_t)(value >> 24); + buffer[5U] = (uint8_t)(value >> 16); + buffer[6U] = (uint8_t)(value >> 8); + buffer[7U] = (uint8_t)(value); } -const unsigned char* load_resource_data(const wchar_t *const name, unsigned int *const length) +uint64_t load_uint64(const unsigned char *const buffer) { + return + (((uint64_t)buffer[0U]) << 56) | + (((uint64_t)buffer[1U]) << 48) | + (((uint64_t)buffer[2U]) << 40) | + (((uint64_t)buffer[3U]) << 32) | + (((uint64_t)buffer[4U]) << 24) | + (((uint64_t)buffer[5U]) << 16) | + (((uint64_t)buffer[6U]) << 8) | + (((uint64_t)buffer[7U])); +} + +/*-------------------------------------------------------*/ +/* load_resource_data() */ +/*-------------------------------------------------------*/ + +const unsigned char* load_resource_data(const CHAR_T *const name, unsigned int *const length) +{ +#ifdef _WIN32 HRSRC resource = FindResourceW(NULL, name, RT_RCDATA); if (resource) { @@ -145,18 +219,22 @@ const unsigned char* load_resource_data(const wchar_t *const name, unsigned int } } } +#endif *length = 0U; return NULL; } +/*-------------------------------------------------------*/ +/* force_flush() */ +/*-------------------------------------------------------*/ + int force_flush(FILE *const file) { const int result = fflush(file); +#ifdef _WIN32 FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(file))); +#else + fsync(fileno(file)); +#endif return (result == 0); } - -void zero_memory(void *const ptr, const size_t size) -{ - SecureZeroMemory(ptr, size); -} diff --git a/src/common.h b/src/common.h index b5c4e17..0613c6c 100644 --- a/src/common.h +++ b/src/common.h @@ -6,21 +6,19 @@ #ifndef _COMMON_H #define _COMMON_H -#include -#include +#include "platform.h" +#include #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 *convert_CHAR_to_UTF8(const CHAR_T *str); 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); +uint64_t get_current_time_usec(void); +void store_uint64(unsigned char *const buffer, const uint64_t value); +uint64_t load_uint64(const unsigned char *const buffer); +const unsigned char* load_resource_data(const CHAR_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*/ diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000..bbbbd1d --- /dev/null +++ b/src/platform.h @@ -0,0 +1,29 @@ +#ifndef _PLATFORM_H +#define _PLATFORM_H + +#include "platform.h" +#include +#include +#include + +#ifdef _WIN32 +#include + +#define CHAR_T wchar_t +#define MAIN wmain +#define FOPEN(X,Y) _wfsopen((X),(Y),_SH_SECURE) +#define MSIZE(X) _msize((X)) +#define _T(X) L##X +#define T(X) _T(X) + +#else + +#define CHAR_T char +#define MAIN main +#define FOPEN(X,Y) fopen((X),(Y)) +#define MSIZE(X) malloc_usable_size((X)) +#define T(X) X + +#endif + +#endif /*_PLATFORM_H*/ diff --git a/utilities/PasswordDialog/App.config b/utilities/PasswordDialog/App.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/utilities/PasswordDialog/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/utilities/PasswordDialog/App.xaml b/utilities/PasswordDialog/App.xaml new file mode 100644 index 0000000..b71b3a7 --- /dev/null +++ b/utilities/PasswordDialog/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/utilities/PasswordDialog/App.xaml.cs b/utilities/PasswordDialog/App.xaml.cs new file mode 100644 index 0000000..cbcc064 --- /dev/null +++ b/utilities/PasswordDialog/App.xaml.cs @@ -0,0 +1,22 @@ +/******************************************************************************/ +/* CodeSign, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace PasswordDialog +{ + /// + /// Interaktionslogik für "App.xaml" + /// + public partial class App : Application + { + } +} diff --git a/utilities/PasswordDialog/MainWindow.xaml b/utilities/PasswordDialog/MainWindow.xaml new file mode 100644 index 0000000..acc6ef5 --- /dev/null +++ b/utilities/PasswordDialog/MainWindow.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/utilities/PasswordDialog/MainWindow.xaml.cs b/utilities/PasswordDialog/MainWindow.xaml.cs new file mode 100644 index 0000000..1a72309 --- /dev/null +++ b/utilities/PasswordDialog/MainWindow.xaml.cs @@ -0,0 +1,116 @@ +/******************************************************************************/ +/* CodeSign, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Interop; +using System.Windows.Threading; + +namespace PasswordDialog +{ + /// + /// Interaktionslogik für MainWindow.xaml + /// + public partial class MainWindow : Window + { + private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); + private const UInt32 SWP_NOSIZE = 0x0001; + private const UInt32 SWP_NOMOVE = 0x0002; + private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; + + private readonly DispatcherTimer dispatcherTimer; + private readonly WindowInteropHelper interopHelper; + + public MainWindow() + { + InitializeComponent(); + dispatcherTimer = new DispatcherTimer(DispatcherPriority.Background); + interopHelper = new WindowInteropHelper(this); + } + + //------------------------------------------------------------------- + // Event Handlers + //------------------------------------------------------------------- + + protected override void OnContentRendered(EventArgs e) + { + IntPtr handle = interopHelper.Handle; + SetForegroundWindow(handle); + SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); + + PasswordBox.Focus(); + + dispatcherTimer.Tick += OnTimerTick; + dispatcherTimer.Interval = TimeSpan.FromMinutes(3); + dispatcherTimer.Start(); + } + + private void Button_OK_Click(object sender, RoutedEventArgs e) + { + if (Button_OK.IsEnabled) + { + using (SecureWrapper wrapper = new SecureWrapper(PasswordBox.SecurePassword)) + { + byte[] buffer = wrapper.ByteBuffer; + using (Stream stdout = Console.OpenStandardOutput()) + { + stdout.Write(buffer, 0, buffer.Length); + stdout.Flush(); + } + } + Close(); /*password was entered, now exit!*/ + } + } + + private void Button_Close_Click(object sender, RoutedEventArgs e) + { + Close(); /*aborted*/ + } + + private void Window_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) + { + if (e.Key == System.Windows.Input.Key.Escape) + { + e.Handled = true; + Close(); + } + } + + private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e) + { + Button_OK.IsEnabled = (PasswordBox.SecurePassword.Length > 0); + } + + private void PasswordBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) + { + if (e.Key == System.Windows.Input.Key.Enter) + { + e.Handled = true; + Dispatcher.InvokeAsync(() => Button_OK_Click(sender, e)); + } + } + + private void OnTimerTick(object sender, EventArgs e) + { + dispatcherTimer.Stop(); + Close(); + } + + //------------------------------------------------------------------- + // Native Methods + //------------------------------------------------------------------- + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool SetForegroundWindow(IntPtr hWnd); + } +} diff --git a/utilities/PasswordDialog/PasswordDialog.csproj b/utilities/PasswordDialog/PasswordDialog.csproj new file mode 100644 index 0000000..8102052 --- /dev/null +++ b/utilities/PasswordDialog/PasswordDialog.csproj @@ -0,0 +1,115 @@ + + + + + Debug + AnyCPU + {833EC8FB-054C-42FF-9F76-33A8DBCAF967} + Exe + Properties + PasswordDialog + passentry + v4.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + + + prompt + 4 + Off + + + PasswordDialog.App + + + Resources\Icon.ico + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + \ No newline at end of file diff --git a/utilities/PasswordDialog/PasswordDialog.sln b/utilities/PasswordDialog/PasswordDialog.sln new file mode 100644 index 0000000..c2323bf --- /dev/null +++ b/utilities/PasswordDialog/PasswordDialog.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PasswordDialog", "PasswordDialog.csproj", "{833EC8FB-054C-42FF-9F76-33A8DBCAF967}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {833EC8FB-054C-42FF-9F76-33A8DBCAF967}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {833EC8FB-054C-42FF-9F76-33A8DBCAF967}.Debug|Any CPU.Build.0 = Debug|Any CPU + {833EC8FB-054C-42FF-9F76-33A8DBCAF967}.Release|Any CPU.ActiveCfg = Release|Any CPU + {833EC8FB-054C-42FF-9F76-33A8DBCAF967}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/utilities/PasswordDialog/Properties/AssemblyInfo.cs b/utilities/PasswordDialog/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ef72ccb --- /dev/null +++ b/utilities/PasswordDialog/Properties/AssemblyInfo.cs @@ -0,0 +1,53 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("CodeSign - PasswordDialog")] +[assembly: AssemblyDescription("CodeSign - PasswordDialog")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Muldersoft")] +[assembly: AssemblyProduct("CodeSign")] +[assembly: AssemblyCopyright("Created by LoRd_MuldeR ")] +[assembly: AssemblyTrademark("Muldersoft")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie +//ImCodeVerwendeteKultur in der .csproj-Datei +//in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch +//(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung +//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile, +//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher + //(wird verwendet, wenn eine Ressource auf der Seite + // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.) + ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs + //(wird verwendet, wenn eine Ressource auf der Seite, in der Anwendung oder einem + // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.) +)] + + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/utilities/PasswordDialog/Properties/Resources.Designer.cs b/utilities/PasswordDialog/Properties/Resources.Designer.cs new file mode 100644 index 0000000..ef40d2d --- /dev/null +++ b/utilities/PasswordDialog/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace PasswordDialog.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PasswordDialog.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/utilities/PasswordDialog/Properties/Resources.resx b/utilities/PasswordDialog/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/utilities/PasswordDialog/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/utilities/PasswordDialog/Properties/Settings.Designer.cs b/utilities/PasswordDialog/Properties/Settings.Designer.cs new file mode 100644 index 0000000..54b5b5c --- /dev/null +++ b/utilities/PasswordDialog/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace PasswordDialog.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/utilities/PasswordDialog/Properties/Settings.settings b/utilities/PasswordDialog/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/utilities/PasswordDialog/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/utilities/PasswordDialog/Resources/Icon.ico b/utilities/PasswordDialog/Resources/Icon.ico new file mode 100644 index 0000000..c10c8f8 Binary files /dev/null and b/utilities/PasswordDialog/Resources/Icon.ico differ diff --git a/utilities/PasswordDialog/SecureWrapper.cs b/utilities/PasswordDialog/SecureWrapper.cs new file mode 100644 index 0000000..2550675 --- /dev/null +++ b/utilities/PasswordDialog/SecureWrapper.cs @@ -0,0 +1,186 @@ +/******************************************************************************/ +/* CodeSign, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace PasswordDialog +{ + public class SecureWrapper : IDisposable + { + private static readonly char[] EMPTY_CHARS = new char[0]; + private static readonly byte[] EMPTY_BYTES = new byte[0]; + + private readonly SecureString m_string; + private readonly Object m_lock = new Object(); + + private GCHandle m_charBuffer; + private GCHandle m_byteBuffer; + + private volatile bool m_disposed = false; + + //------------------------------------------------------------------- + // Constructor + //------------------------------------------------------------------- + + public SecureWrapper(SecureString secureString) + { + if(ReferenceEquals(m_string = secureString, null)) + { + throw new ArgumentNullException("SecureString must not be null!"); + } + } + + ~SecureWrapper() + { + Dispose(); + } + + //------------------------------------------------------------------- + // Public Interface + //------------------------------------------------------------------- + + public char[] CharBuffer + { + get + { + lock(m_lock) + { + if(m_disposed) + { + throw new ObjectDisposedException("Already disposed!"); + } + if(m_string.Length > 0) + { + if (!m_charBuffer.IsAllocated) + { + m_charBuffer = AllocateBuffer(m_string.Length); + try + { + CopyToBuffer((char[])m_charBuffer.Target, m_string); + } + catch + { + ClearBuffer(m_charBuffer); + throw; /*re-throw after clean-up!*/ + } + } + return (char[])m_charBuffer.Target; + } + return EMPTY_CHARS; + } + } + } + + public byte[] ByteBuffer + { + get + { + lock (m_lock) + { + if(m_disposed) + { + throw new ObjectDisposedException("Already disposed!"); + } + if (m_string.Length > 0) + { + if (!m_byteBuffer.IsAllocated) + { + UTF8Encoding encoding = new UTF8Encoding(false); + char[] chars = CharBuffer; + m_byteBuffer = AllocateBuffer(encoding.GetByteCount(chars)); + try + { + encoding.GetBytes(chars, 0, chars.Length, (byte[])m_byteBuffer.Target, 0); + } + catch + { + ClearBuffer(m_byteBuffer); + throw; /*re-throw after clean-up!*/ + } + } + return (byte[])m_byteBuffer.Target; + } + return EMPTY_BYTES; + } + } + } + + public void Dispose() + { + lock (m_lock) + { + if (!m_disposed) + { + m_disposed = true; + try + { + ClearBuffer(m_byteBuffer); + } + catch { } + try + { + ClearBuffer(m_charBuffer); + } + catch { } + } + } + } + + //------------------------------------------------------------------- + // Internal Methods + //------------------------------------------------------------------- + + private static GCHandle AllocateBuffer(int length) + { + T[] buffer = new T[length]; + return GCHandle.Alloc(buffer, GCHandleType.Pinned); + } + + private static void CopyToBuffer(char[] buffer, SecureString secStr) + { + IntPtr valuePtr = IntPtr.Zero; + try + { + valuePtr = Marshal.SecureStringToGlobalAllocUnicode(secStr); + Marshal.Copy(valuePtr, buffer, 0, Math.Min(secStr.Length, buffer.Length)); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(valuePtr); + } + } + + private static void ClearBuffer(GCHandle handle) + { + if(handle.IsAllocated) + { + try + { + if(handle.Target is Array) + { + Array array = (Array)handle.Target; + Array.Clear(array, 0, array.Length); + } + else if(handle.Target is String) + { + char[] zeros = new char[((String)handle.Target).Length]; + Marshal.Copy(zeros, 0, handle.AddrOfPinnedObject(), zeros.Length); + } + else + { + throw new ArgumentException("Unsupported buffer type!"); + } + } + finally + { + handle.Free(); + } + } + } + } +}