2
0

Build support for Microsoft Windows.

This commit is contained in:
Maarten Billemont 2018-06-24 16:20:42 -04:00
parent 5a4456bf46
commit fffec56d4e
17 changed files with 169 additions and 201 deletions

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value />
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Lhunath" />
</component>
</project>

View File

@ -1,7 +0,0 @@
<component name="CopyrightManager">
<copyright>
<option name="keyword" value="Copyright|License|WARRANTY" />
<option name="myName" value="GPLv3" />
<option name="notice" value="This file is part of &amp;#36;project.name.&#10;Copyright (c) &amp;#36;today.year.&#10;&#10;&amp;#36;project.name is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;&amp;#36;project.name is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10;&#10;You can find a copy of the GNU General Public License in the&#10;LICENSE file. Alternatively, see &lt;http://www.gnu.org/licenses/&gt;." />
</copyright>
</component>

View File

@ -1,13 +0,0 @@
<component name="CopyrightManager">
<settings>
<module2copyright>
<element module="masterpassword" copyright="Master Password" />
</module2copyright>
<LanguageOptions name="__TEMPLATE__">
<option name="block" value="false" />
<option name="separateBefore" value="true" />
<option name="separateAfter" value="true" />
<option name="filler" value="=" />
</LanguageOptions>
</settings>
</component>

View File

@ -1,9 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="projectProfile" value="Lhunath" />
<option name="useProjectProfile" value="false" />
<option name="PROJECT_PROFILE" value="Lhunath" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -1,45 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="FrameworkDetectionExcludesConfiguration"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<type id="jpa" /> <output url="file://$PROJECT_DIR$/build/classes" />
<type id="web" />
</component> </component>
<component name="MavenProjectsManager"> <component name="ProjectType">
<option name="originalFiles"> <option name="id" value="Android" />
<list>
<option value="$PROJECT_DIR$/../../opal/pom.xml" />
<option value="$PROJECT_DIR$/../../pom.xml" />
</list>
</option>
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="javax.annotation.Nullable" />
<option name="myDefaultNotNull" value="javax.annotation.Nonnull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/classes" />
</component>
<component name="ThriftCompiler">
<compilers />
</component> </component>
</project> </project>

View File

@ -1,28 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Android" type="AndroidRunConfigurationType" factoryName="Android App">
<module name="android" />
<option name="DEPLOY" value="true" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="PREFERRED_AVD" value="" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="TARGET_SELECTION_MODE" value="SHOW_DIALOG" />
<option name="USE_LAST_SELECTED_DEVICE" value="false" />
<option name="PREFERRED_AVD" value="" />
<option name="DEBUGGER_TYPE" value="Java" />
<Java />
<Profilers>
<option name="ENABLE_ADVANCED_PROFILING" value="false" />
<option name="SUPPORT_LIB_ENABLED" value="true" />
<option name="INSTRUMENTATION_ENABLED" value="true" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<method />
</configuration>
</component>

View File

@ -1,3 +0,0 @@
<component name="DependencyValidationManager">
<scope name="masterpassword" pattern="com.lyndir.masterpassword..*" />
</component>

View File

@ -1,5 +1,6 @@
#Fri Jun 22 01:12:28 EDT 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip

View File

@ -21,9 +21,9 @@ project(':masterpassword-tests').projectDir = new File( '../platform-independent
include 'masterpassword-gui' include 'masterpassword-gui'
project(':masterpassword-gui').projectDir = new File( '../platform-independent/java/gui' ) project(':masterpassword-gui').projectDir = new File( '../platform-independent/java/gui' )
if (local.containsKey('sdk.dir')) { //if (local.containsKey('sdk.dir')) {
include 'masterpassword-android' include 'masterpassword-android'
project(':masterpassword-android').projectDir = new File( '../platform-android' ) project(':masterpassword-android').projectDir = new File( '../platform-android' )
} else { //} else {
logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." ) // logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." )
} //}

View File

@ -53,7 +53,13 @@ _initialize() {
# By default, this will check for `automake` and `autoreconf`. # By default, this will check for `automake` and `autoreconf`.
initialize_needs() { _initialize_needs "$@"; } initialize_needs() { _initialize_needs "$@"; }
_initialize_needs() { _initialize_needs() {
needs automake autoreconf if [[ $platform = windows ]]; then
needs cmd
export VSINSTALLDIR="${VSINSTALLDIR:-$(cd "$(cygpath -F 0x002a)/Microsoft Visual Studio"/*/*/Common7/.. && pwd)}"
[[ -e "$VSINSTALLDIR/Common7/Tools/VsMSBuildCmd.bat" ]] || { echo >&2 "Missing: msbuild. Please install 'Build Tools for Visual Studio'."; return 1; }
else
needs automake autoreconf
fi
} }
# clean <prefix> <platform> # clean <prefix> <platform>
@ -64,6 +70,13 @@ _initialize_needs() {
clean() { _clean "$@"; } clean() { _clean "$@"; }
_clean() { _clean() {
rm -rf "$prefix" rm -rf "$prefix"
if [[ $platform = windows ]]; then
printf '"%%VSINSTALLDIR%%\Common7\Tools\VsMSBuildCmd.bat" && msbuild /t:Clean' > .clean.bat
cmd //c .clean.bat
rm -f .clean.bat
fi
[[ ! -e Makefile ]] || make -s distclean [[ ! -e Makefile ]] || make -s distclean
[[ ! -e .git ]] || git clean -fdx [[ ! -e .git ]] || git clean -fdx
} }
@ -103,6 +116,8 @@ prepare_config() { _prepare_config "$@"; }
_prepare_config() { _prepare_config() {
local prefix=$1 platform=$2; shift 2 local prefix=$1 platform=$2; shift 2
[[ $platform = windows ]] && return
[[ -e configure ]] || autoreconf --verbose --install --symlink 2> >(sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /') [[ -e configure ]] || autoreconf --verbose --install --symlink 2> >(sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /')
} }
@ -127,6 +142,8 @@ target_prepare() { _target_prepare "$@"; }
_target_prepare() { _target_prepare() {
local prefix=$1 platform=$2 arch=$3; shift 3 local prefix=$1 platform=$2 arch=$3; shift 3
[[ $platform = windows ]] && return
[[ ! -e Makefile ]] || make -s clean [[ ! -e Makefile ]] || make -s clean
} }
@ -140,6 +157,9 @@ _target_configure() {
local prefix=$1 platform=$2 arch=$3; shift 3 local prefix=$1 platform=$2 arch=$3; shift 3
case "$platform" in case "$platform" in
'windows')
return
;;
'android') 'android')
host=( "$SDKROOT"/*-android* ) host=${host##*/} host=( "$SDKROOT"/*-android* ) host=${host##*/}
@ -164,10 +184,16 @@ _target_configure() {
target_build() { _target_build "$@"; } target_build() { _target_build "$@"; }
_target_build() { _target_build() {
local prefix=$1 platform=$2 arch=$3; shift 3 local prefix=$1 platform=$2 arch=$3; shift 3
#make -j3 check
cores=$(getconf NPROCESSORS_ONLN 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null ||:) if [[ $platform = windows ]]; then
make -j"${cores:-3}" install # I cannot for the life of me figure out how to pass this command directly into cmd.
printf '"%%VSINSTALLDIR%%\Common7\Tools\VsMSBuildCmd.bat" && msbuild /t:Rebuild /p:Configuration=ReleaseDLL;Platform=%s;OutDir=%s' "$arch" "$(cygpath -w "${prefix##$PWD/}/$arch/")" > .build.bat
cmd //c .build.bat
rm -f .build.bat
else
local cores=$(getconf NPROCESSORS_ONLN 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null ||:)
make -j"${cores:-3}" install
fi
} }
# finalize <prefix> <platform> [ <arch> ... ] # finalize <prefix> <platform> [ <arch> ... ]
@ -189,10 +215,16 @@ finalize_merge() { _finalize_merge "$@"; }
_finalize_merge() { _finalize_merge() {
local prefix=$1 platform=$2; shift 2 local prefix=$1 platform=$2; shift 2
mv -f -- "$prefix/$1/include" "$prefix/out/" [[ -e "$prefix/$1/include" ]] && mv -f -- "$prefix/$1/include" "$prefix/out/"
mkdir -p "$prefix/out/lib" mkdir -p "$prefix/out/lib"
case "$platform" in case "$platform" in
'windows')
for arch; do
install -d "$prefix/out/lib/$arch"
install -p "$prefix/Win32/"*.lib "$prefix/out/lib/"
done
;;
'macos'|'ios') 'macos'|'ios')
for lib in "$prefix/$1/lib/"*; do for lib in "$prefix/$1/lib/"*; do
if lipo -info "$lib" >/dev/null 2>&1; then if lipo -info "$lib" >/dev/null 2>&1; then
@ -247,6 +279,7 @@ _build() {
'macos') archs=( 'x86_64' ) ;; 'macos') archs=( 'x86_64' ) ;;
'ios') archs=( 'i386' 'x86_64' 'armv7' 'armv7s' 'arm64' ) ;; 'ios') archs=( 'i386' 'x86_64' 'armv7' 'armv7s' 'arm64' ) ;;
'android') archs=( 'arm' 'arm64' 'x86' 'x86_64' ) ;; 'android') archs=( 'arm' 'arm64' 'x86' 'x86_64' ) ;;
'windows') archs=( 'Win32' 'x64' ) ;;
esac esac
fi fi
@ -270,6 +303,8 @@ _build() {
# Set up a base environment for the platform. # Set up a base environment for the platform.
case "$platform" in case "$platform" in
'windows')
;;
'macos') 'macos')
SDKROOT="$(xcrun --show-sdk-path --sdk macosx)" SDKROOT="$(xcrun --show-sdk-path --sdk macosx)"
export PATH="$(xcrun --show-sdk-platform-path --sdk macosx)/usr/bin:$PATH" export PATH="$(xcrun --show-sdk-platform-path --sdk macosx)/usr/bin:$PATH"

View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
source "${BASH_SOURCE%/*}/build_lib"
autoreconf() {
command autoreconf -Iautoconf-archive/m4 "$@"
}
build libjson-c windows

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
source "${BASH_SOURCE%/*}/build_lib"
build libsodium windows

View File

@ -21,10 +21,15 @@ artifacts {
} }
library { library {
linkage.set( [Linkage.STATIC, Linkage.SHARED] ) linkage.set( [ Linkage.SHARED ] )
// Reconfigure the toolchain from C++ to C. // Reconfigure the toolchain from C++ to C.
toolChains { toolChains {
withType( VisualCpp ) {
eachPlatform {
cppCompiler.withArguments { addAll( ["/TC", "/DMPW_SODIUM=1"] ) }
}
}
withType( GccCompatibleToolChain ) { withType( GccCompatibleToolChain ) {
eachPlatform { eachPlatform {
cppCompiler.withArguments { addAll( ["-x", "c", "-std=c11", "-Werror", "-DMPW_SODIUM=1"] ) } cppCompiler.withArguments { addAll( ["-x", "c", "-std=c11", "-Werror", "-DMPW_SODIUM=1"] ) }
@ -52,7 +57,7 @@ library {
// Depend on libsodium from `lib`; run `lib/bin/build_libsodium-${platform}` first. // Depend on libsodium from `lib`; run `lib/bin/build_libsodium-${platform}` first.
add( includePathConfiguration.name, add( includePathConfiguration.name,
files( "../../../lib/libsodium/build-${platform}~/out/include" ) ) files( "../../../lib/libsodium/src/libsodium/include" ) )
add( linkLibraries.name, add( linkLibraries.name,
fileTree( "../../../lib/libsodium/build-${platform}~/out/lib" ) ) fileTree( "../../../lib/libsodium/build-${platform}~/out/lib" ) )
} }

View File

@ -206,7 +206,7 @@ static bool mpw_marshal_write_flat(
if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) )) if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) ))
mpw_string_pushf( out, "%s %8ld %lu:%lu:%lu %25s\t%25s\t%s\n", mpw_string_pushf( out, "%s %8ld %lu:%lu:%lu %25s\t%25s\t%s\n",
dateString, (long)site->uses, (long)site->type, (long)site->algorithm, (long)site->counter, dateString, (long)site->uses, (long)site->type, (long)site->algorithm, (long)site->counter,
loginContent?: "", site->name, content?: "" ); loginContent? loginContent: "", site->name, content? content: "" );
mpw_free_strings( &content, &loginContent, NULL ); mpw_free_strings( &content, &loginContent, NULL );
} }
mpw_free( &masterKey, MPMasterKeySize ); mpw_free( &masterKey, MPMasterKeySize );
@ -871,21 +871,14 @@ const MPMarshalFormat mpw_formatWithName(
if (!formatName || !strlen( formatName )) if (!formatName || !strlen( formatName ))
return MPMarshalFormatNone; return MPMarshalFormatNone;
// Lower-case to standardize it. if (mpw_strncasecmp( mpw_nameForFormat( MPMarshalFormatNone ), formatName, strlen( formatName ) ) == 0)
size_t stdFormatNameSize = strlen( formatName );
char stdFormatName[stdFormatNameSize + 1];
for (size_t c = 0; c < stdFormatNameSize; ++c)
stdFormatName[c] = (char)tolower( formatName[c] );
stdFormatName[stdFormatNameSize] = '\0';
if (strncmp( mpw_nameForFormat( MPMarshalFormatNone ), stdFormatName, strlen( stdFormatName ) ) == 0)
return MPMarshalFormatNone; return MPMarshalFormatNone;
if (strncmp( mpw_nameForFormat( MPMarshalFormatFlat ), stdFormatName, strlen( stdFormatName ) ) == 0) if (mpw_strncasecmp( mpw_nameForFormat( MPMarshalFormatFlat ), formatName, strlen( formatName ) ) == 0)
return MPMarshalFormatFlat; return MPMarshalFormatFlat;
if (strncmp( mpw_nameForFormat( MPMarshalFormatJSON ), stdFormatName, strlen( stdFormatName ) ) == 0) if (mpw_strncasecmp( mpw_nameForFormat( MPMarshalFormatJSON ), formatName, strlen( formatName ) ) == 0)
return MPMarshalFormatJSON; return MPMarshalFormatJSON;
dbg( "Not a format name: %s", stdFormatName ); dbg( "Not a format name: %s", formatName );
return (MPMarshalFormat)ERR; return (MPMarshalFormat)ERR;
} }

View File

@ -53,38 +53,31 @@ const MPResultType mpw_typeWithName(const char *typeName) {
return MPResultTypeDeriveKey; return MPResultTypeDeriveKey;
} }
// Lower-case typeName to standardize it.
size_t stdTypeNameSize = strlen( typeName );
char stdTypeName[stdTypeNameSize + 1];
for (size_t c = 0; c < stdTypeNameSize; ++c)
stdTypeName[c] = (char)tolower( typeName[c] );
stdTypeName[stdTypeNameSize] = '\0';
// Find what password type is represented by the type name. // Find what password type is represented by the type name.
if (strncmp( mpw_nameForType( MPResultTypeTemplateMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateMaximum ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplateMaximum; return MPResultTypeTemplateMaximum;
if (strncmp( mpw_nameForType( MPResultTypeTemplateLong ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateLong ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplateLong; return MPResultTypeTemplateLong;
if (strncmp( mpw_nameForType( MPResultTypeTemplateMedium ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateMedium ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplateMedium; return MPResultTypeTemplateMedium;
if (strncmp( mpw_nameForType( MPResultTypeTemplateBasic ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateBasic ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplateBasic; return MPResultTypeTemplateBasic;
if (strncmp( mpw_nameForType( MPResultTypeTemplateShort ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateShort ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplateShort; return MPResultTypeTemplateShort;
if (strncmp( mpw_nameForType( MPResultTypeTemplatePIN ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplatePIN ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplatePIN; return MPResultTypeTemplatePIN;
if (strncmp( mpw_nameForType( MPResultTypeTemplateName ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateName ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplateName; return MPResultTypeTemplateName;
if (strncmp( mpw_nameForType( MPResultTypeTemplatePhrase ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplatePhrase ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeTemplatePhrase; return MPResultTypeTemplatePhrase;
if (strncmp( mpw_nameForType( MPResultTypeStatefulPersonal ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeStatefulPersonal ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeStatefulPersonal; return MPResultTypeStatefulPersonal;
if (strncmp( mpw_nameForType( MPResultTypeStatefulDevice ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeStatefulDevice ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeStatefulDevice; return MPResultTypeStatefulDevice;
if (strncmp( mpw_nameForType( MPResultTypeDeriveKey ), stdTypeName, strlen( stdTypeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForType( MPResultTypeDeriveKey ), typeName, strlen( typeName ) ) == 0)
return MPResultTypeDeriveKey; return MPResultTypeDeriveKey;
dbg( "Not a generated type name: %s", stdTypeName ); dbg( "Not a generated type name: %s", typeName );
return (MPResultType)ERR; return (MPResultType)ERR;
} }
@ -129,35 +122,35 @@ const char **mpw_templatesForType(MPResultType type, size_t *count) {
switch (type) { switch (type) {
case MPResultTypeTemplateMaximum: case MPResultTypeTemplateMaximum:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" ); "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno", NULL );
case MPResultTypeTemplateLong: case MPResultTypeTemplateLong:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
"CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno",
"CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno",
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" ); "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno", NULL );
case MPResultTypeTemplateMedium: case MPResultTypeTemplateMedium:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"CvcnoCvc", "CvcCvcno" ); "CvcnoCvc", "CvcCvcno", NULL );
case MPResultTypeTemplateShort: case MPResultTypeTemplateShort:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"Cvcn" ); "Cvcn", NULL );
case MPResultTypeTemplateBasic: case MPResultTypeTemplateBasic:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"aaanaaan", "aannaaan", "aaannaaa" ); "aaanaaan", "aannaaan", "aaannaaa", NULL );
case MPResultTypeTemplatePIN: case MPResultTypeTemplatePIN:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"nnnn" ); "nnnn", NULL );
case MPResultTypeTemplateName: case MPResultTypeTemplateName:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"cvccvcvcv" ); "cvccvcvcv", NULL );
case MPResultTypeTemplatePhrase: case MPResultTypeTemplatePhrase:
return mpw_alloc_array( count, const char *, return mpw_strings( count,
"cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" ); "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv", NULL );
default: { default: {
dbg( "Unknown generated type: %d", type ); dbg( "Unknown generated type: %d", type );
return NULL; return NULL;
@ -177,21 +170,14 @@ const char *mpw_templateForType(MPResultType type, uint8_t templateIndex) {
const MPKeyPurpose mpw_purposeWithName(const char *purposeName) { const MPKeyPurpose mpw_purposeWithName(const char *purposeName) {
// Lower-case and trim optionally leading "generated" string from typeName to standardize it. if (mpw_strncasecmp( mpw_nameForPurpose( MPKeyPurposeAuthentication ), purposeName, strlen( purposeName ) ) == 0)
size_t stdPurposeNameSize = strlen( purposeName );
char stdPurposeName[stdPurposeNameSize + 1];
for (size_t c = 0; c < stdPurposeNameSize; ++c)
stdPurposeName[c] = (char)tolower( purposeName[c] );
stdPurposeName[stdPurposeNameSize] = '\0';
if (strncmp( mpw_nameForPurpose( MPKeyPurposeAuthentication ), stdPurposeName, strlen( stdPurposeName ) ) == 0)
return MPKeyPurposeAuthentication; return MPKeyPurposeAuthentication;
if (strncmp( mpw_nameForPurpose( MPKeyPurposeIdentification ), stdPurposeName, strlen( stdPurposeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForPurpose( MPKeyPurposeIdentification ), purposeName, strlen( purposeName ) ) == 0)
return MPKeyPurposeIdentification; return MPKeyPurposeIdentification;
if (strncmp( mpw_nameForPurpose( MPKeyPurposeRecovery ), stdPurposeName, strlen( stdPurposeName ) ) == 0) if (mpw_strncasecmp( mpw_nameForPurpose( MPKeyPurposeRecovery ), purposeName, strlen( purposeName ) ) == 0)
return MPKeyPurposeRecovery; return MPKeyPurposeRecovery;
dbg( "Not a purpose name: %s", stdPurposeName ); dbg( "Not a purpose name: %s", purposeName );
return (MPKeyPurpose)ERR; return (MPKeyPurpose)ERR;
} }

View File

@ -62,6 +62,25 @@ void mpw_uint64(const uint64_t number, uint8_t buf[8]) {
buf[7] = (uint8_t)((number >> 0L) & UINT8_MAX); buf[7] = (uint8_t)((number >> 0L) & UINT8_MAX);
} }
const char **mpw_strings(size_t *count, const char *strings, ...) {
va_list args;
va_start( args, strings );
char **array = NULL;
size_t arraySize = 0;
for (const char *string; string = va_arg( args, const char * );) {
size_t cursor = arraySize;
if (!mpw_realloc( &array, &arraySize, sizeof(string) )) {
mpw_free( &array, arraySize );
return NULL;
}
array[cursor] = string;
}
va_end( args );
return array;
}
bool mpw_push_buf(uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize) { bool mpw_push_buf(uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize) {
if (!buffer || !bufferSize || !pushBuffer || !pushSize) if (!buffer || !bufferSize || !pushBuffer || !pushSize)
@ -275,14 +294,15 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key
return NULL; return NULL;
// IV = zero // IV = zero
uint8_t iv[AES_BLOCKLEN]; static uint8_t *iv = NULL;
mpw_zero( iv, sizeof iv ); if (!iv)
iv = calloc( AES_BLOCKLEN, sizeof( uint8_t ) );
// Add PKCS#7 padding // Add PKCS#7 padding
uint32_t aesSize = ((uint32_t)*bufSize + AES_BLOCKLEN - 1) & -AES_BLOCKLEN; // round up to block size. uint32_t aesSize = ((uint32_t)*bufSize + AES_BLOCKLEN - 1) & -AES_BLOCKLEN; // round up to block size.
if (encrypt && !(*bufSize % AES_BLOCKLEN)) // add pad block if plain text fits block size. if (encrypt && !(*bufSize % AES_BLOCKLEN)) // add pad block if plain text fits block size.
encrypt += AES_BLOCKLEN; encrypt += AES_BLOCKLEN;
uint8_t aesBuf[aesSize]; uint8_t *aesBuf = malloc( aesSize );
memcpy( aesBuf, buf, *bufSize ); memcpy( aesBuf, buf, *bufSize );
memset( aesBuf + *bufSize, aesSize - *bufSize, aesSize - *bufSize ); memset( aesBuf + *bufSize, aesSize - *bufSize, aesSize - *bufSize );
uint8_t *resultBuf = malloc( aesSize ); uint8_t *resultBuf = malloc( aesSize );
@ -291,8 +311,7 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key
AES_CBC_encrypt_buffer( resultBuf, aesBuf, aesSize, key, iv ); AES_CBC_encrypt_buffer( resultBuf, aesBuf, aesSize, key, iv );
else else
AES_CBC_decrypt_buffer( resultBuf, aesBuf, aesSize, key, iv ); AES_CBC_decrypt_buffer( resultBuf, aesBuf, aesSize, key, iv );
mpw_zero( aesBuf, aesSize ); mpw_free( aesBuf, aesSize );
mpw_zero( iv, AES_BLOCKLEN );
// Truncate PKCS#7 padding // Truncate PKCS#7 padding
if (encrypt) if (encrypt)
@ -496,3 +515,15 @@ char *mpw_strndup(const char *src, size_t max) {
return dst; return dst;
} }
int *mpw_strncasecmp(const char *s1, const char *s2, size_t max) {
if (s1 && s2 && max)
for (; --max > 0; ++s1, ++s2) {
int cmp = tolower( *(unsigned char *)s1 ) - tolower( *(unsigned char *)s2 );
if (!cmp || *s1 == '\0')
return cmp;
}
return 0;
}

View File

@ -33,36 +33,36 @@ extern int mpw_verbosity;
#endif #endif
#ifndef mpw_log #ifndef mpw_log
#define mpw_log(level, ...) ({ \ #define mpw_log(level, format, ...) do { \
if (mpw_verbosity >= level) { \ if (mpw_verbosity >= level) { \
mpw_log_do( level, ##__VA_ARGS__ ); \ mpw_log_do( level, format, ##__VA_ARGS__ ); \
}; }) }; } while (0)
#endif #endif
#ifndef trc #ifndef trc
/** Logging internal state. */ /** Logging internal state. */
#define trc_level 3 #define trc_level 3
#define trc(...) mpw_log( trc_level, ##__VA_ARGS__ ) #define trc(format, ...) mpw_log( trc_level, format, ##__VA_ARGS__ )
/** Logging state and events interesting when investigating issues. */ /** Logging state and events interesting when investigating issues. */
#define dbg_level 2 #define dbg_level 2
#define dbg(...) mpw_log( dbg_level, ##__VA_ARGS__ ) #define dbg(format, ...) mpw_log( dbg_level, format, ##__VA_ARGS__ )
/** User messages. */ /** User messages. */
#define inf_level 1 #define inf_level 1
#define inf(...) mpw_log( inf_level, ##__VA_ARGS__ ) #define inf(format, ...) mpw_log( inf_level, format, ##__VA_ARGS__ )
/** Recoverable issues and user suggestions. */ /** Recoverable issues and user suggestions. */
#define wrn_level 0 #define wrn_level 0
#define wrn(...) mpw_log( wrn_level, ##__VA_ARGS__ ) #define wrn(format, ...) mpw_log( wrn_level, format, ##__VA_ARGS__ )
/** Unrecoverable issues. */ /** Unrecoverable issues. */
#define err_level -1 #define err_level -1
#define err(...) mpw_log( err_level, ##__VA_ARGS__ ) #define err(format, ...) mpw_log( err_level, format, ##__VA_ARGS__ )
/** Issues that lead to abortion. */ /** Issues that lead to abortion. */
#define ftl_level -2 #define ftl_level -2
#define ftl(...) mpw_log( ftl_level, ##__VA_ARGS__ ) #define ftl(format, ...) mpw_log( ftl_level, format, ##__VA_ARGS__ )
#endif #endif
#ifndef min #ifndef min
@ -98,14 +98,8 @@ void mpw_uint32(const uint32_t number, uint8_t buf[4]);
void mpw_uint64(const uint64_t number, uint8_t buf[8]); void mpw_uint64(const uint64_t number, uint8_t buf[8]);
/** Allocate a new array of _type, assign its element count to _count if not NULL and populate it with the varargs. */ /** Allocate a new array of _type, assign its element count to _count if not NULL and populate it with the varargs. */
#define mpw_alloc_array(_count, _type, ...) ({ \ const char **mpw_strings(
_type stackElements[] = { __VA_ARGS__ }; \ size_t *count, const char *strings, ...);
if (_count) \
*_count = sizeof( stackElements ) / sizeof( _type ); \
_type *allocElements = malloc( sizeof( stackElements ) ); \
memcpy( allocElements, stackElements, sizeof( stackElements ) ); \
allocElements; \
})
/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */ /** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */
bool mpw_push_buf( bool mpw_push_buf(
@ -150,6 +144,20 @@ bool __mpw_free_string(
({ __typeof__(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (char **)_s, __VA_ARGS__ ); }) ({ __typeof__(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (char **)_s, __VA_ARGS__ ); })
bool __mpw_free_strings( bool __mpw_free_strings(
char **strings, ...); char **strings, ...);
#ifdef _MSC_VER
#undef mpw_realloc
#define mpw_realloc(buffer, bufferSize, deltaSize) \
__mpw_realloc( (const void **)buffer, bufferSize, deltaSize )
#undef mpw_free
#define mpw_free(buffer, bufferSize) \
__mpw_free( (void **)buffer, bufferSize )
#undef mpw_free_string
#define mpw_free_string(string) \
__mpw_free_string( (char **)string )
#undef mpw_free_strings
#define mpw_free_strings(strings, ...) \
__mpw_free_strings( (char **)strings, __VA_ARGS__ )
#endif
//// Cryptographic functions. //// Cryptographic functions.
@ -207,5 +215,7 @@ const size_t mpw_utf8_strlen(const char *utf8String);
char *mpw_strdup(const char *src); char *mpw_strdup(const char *src);
/** Drop-in for POSIX strndup(3). */ /** Drop-in for POSIX strndup(3). */
char *mpw_strndup(const char *src, size_t max); char *mpw_strndup(const char *src, size_t max);
/** Drop-in for POSIX strncasecmp(3). */
int *mpw_strncasecmp(const char *s1, const char *s2, size_t max);
#endif // _MPW_UTIL_H #endif // _MPW_UTIL_H