Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
895df6377d | ||
|
|
3d46f60ff4 | ||
|
|
44d8ab6e53 | ||
|
|
cd70009c2c | ||
|
|
4261160902 | ||
|
|
ced7aef5d7 | ||
|
|
63100913c5 | ||
|
|
6904d4c427 | ||
|
|
4271d77225 | ||
|
|
6811773e54 | ||
|
|
060ce61030 | ||
|
|
9a5e9ced31 | ||
|
|
568401a612 | ||
|
|
92a3a0ccbd | ||
|
|
ba24c2be34 | ||
|
|
019cefd3fb | ||
|
|
eef82f7ed4 | ||
|
|
2dfe0f78b0 | ||
|
|
627144b583 | ||
|
|
fad0f5e5dd | ||
|
|
8562338b62 | ||
|
|
17de69834e | ||
|
|
aeeab7dbf6 | ||
|
|
ce60ba6c9f | ||
|
|
d22f93e564 | ||
|
|
6f4f6b8d1e | ||
|
|
6fa8ee53cd | ||
|
|
23af56c150 | ||
|
|
91828cbad7 | ||
|
|
40d2788ae0 | ||
|
|
21a3a28980 | ||
|
|
f5c7bee58f | ||
|
|
e364f5159b | ||
|
|
74f9f1ca00 | ||
|
|
328d38ac19 | ||
|
|
7735d82c7b | ||
|
|
1e7c200865 | ||
|
|
724b357dd8 | ||
|
|
a85efc5736 | ||
|
|
9eb58119ea | ||
|
|
77b4ed2cfd | ||
|
|
011416690a | ||
|
|
53eb5c8a73 | ||
|
|
2f99855cd4 | ||
|
|
18eaeec1de | ||
|
|
5ee700c9b9 | ||
|
|
a8949ca07e | ||
|
|
0a42579d9e | ||
|
|
f2f8747126 | ||
|
|
f83cdacab8 | ||
|
|
98aeb02d32 | ||
|
|
2bbaeccd05 | ||
|
|
91e0a04e66 | ||
|
|
661fc523ad | ||
|
|
b9cbaf7343 | ||
|
|
e451308fdc | ||
|
|
1b51c5efa4 | ||
|
|
a8776eec58 | ||
|
|
d9cdb7ef83 | ||
|
|
28c7a64bd2 | ||
|
|
d7193f7753 | ||
|
|
f5c7d11f0e | ||
|
|
c0ba96daa2 | ||
|
|
b374d9e04a |
16
.gitignore
vendored
16
.gitignore
vendored
@@ -13,8 +13,6 @@ xcuserdata/
|
||||
DerivedData/
|
||||
|
||||
# Generated
|
||||
/platform-independent/cli-c/VERSION
|
||||
/platform-independent/cli-c/mpw-*.tar.gz
|
||||
/platform-darwin/Resources/Media/Images.xcassets/
|
||||
|
||||
# Media
|
||||
@@ -31,17 +29,3 @@ local.properties
|
||||
# Maven
|
||||
target
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
# C
|
||||
core/c/*.o
|
||||
core/c/lib/*/.unpacked
|
||||
core/c/lib/*/.patched
|
||||
core/c/lib/*/src
|
||||
core/c/lib/include
|
||||
platform-independent/cli-c/cli/*.o
|
||||
platform-independent/cli-c/mpw-*.tar.gz
|
||||
platform-independent/cli-c/mpw-*.tar.gz.sig
|
||||
platform-independent/cli-c/mpw
|
||||
platform-independent/cli-c/mpw-bench
|
||||
platform-independent/cli-c/mpw-tests
|
||||
platform-independent/cli-c/VERSION
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -24,4 +24,4 @@
|
||||
url = https://github.com/jedisct1/libsodium.git
|
||||
[submodule "platform-darwin/External/libjson-c"]
|
||||
path = platform-darwin/External/libjson-c
|
||||
url = https://github.com/json-c/json-c.git
|
||||
url = https://github.com/lhunath/json-c.git
|
||||
|
||||
@@ -4,7 +4,7 @@ env: TERM=dumb SHLVL=0
|
||||
git:
|
||||
submodules: true
|
||||
script:
|
||||
- "( brew install libsodium )"
|
||||
- "( cd ./platform-independent/cli-c && ./clean && targets='mpw mpw-bench mpw-tests' ./build && ./mpw-tests )"
|
||||
- "( brew install libsodium json-c )"
|
||||
- "( cd ./platform-independent/cli-c && ./clean && targets='mpw mpw-bench mpw-tests' ./build && ./mpw-tests && ./mpw-cli-tests )"
|
||||
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword iOS' -sdk iphonesimulator )"
|
||||
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword macOS' )"
|
||||
|
||||
44
README.md
44
README.md
@@ -194,49 +194,7 @@ Note that in order to build the Android application, you will need to have the A
|
||||
|
||||
Go into the `platform-independent/cli-c` directory and run `./build`. The native command-line client will then be built.
|
||||
|
||||
When the build completes, you will have an `mpw` binary you can use. You can copy it into your `PATH` or use the `./install` script to help you do so.
|
||||
|
||||
For example:
|
||||
|
||||
./build && sudo ./install
|
||||
mpw -h
|
||||
|
||||
Normally, this is all you need to do, however note that there are a few dependencies that need to be met, depending on which targets you are building (by default, only the `mpw` target is built):
|
||||
|
||||
- `mpw`
|
||||
|
||||
The C implementation depends either on `libsodium` or Tarsnap's `scrypt` and `openssl-dev`.
|
||||
|
||||
We recommend you install `libsodium`. If `libsodium` is not installed when `./build` is executed, the script will try to download and statically link Tarsnap's `scrypt` instead. Tarsnap's `scrypt` depends on you having `openssl-dev` installed.
|
||||
|
||||
If you have `mpw_color` enabled (it is enabled by default), the build also depends on `ncurses-dev` to communicate with the terminal.
|
||||
|
||||
- `mpw-bench`
|
||||
|
||||
This tool compares the performance of a few cryptographic algorithms, including bcrypt. The `./build` script will try to automatically download and statically link `bcrypt`.
|
||||
|
||||
- `mpw-tests`
|
||||
|
||||
This tool runs a suite of tests to ensure the correct passwords are being generated by the algorithm under various circumstances. The test suite is declared in `mpw-tests.xml` which needs to exist in the current working directory when running the tool. In addition, `libxml2` is used to parse the file, so this target depends on you having it installed when running `./build`.
|
||||
|
||||
|
||||
Finally, there are a few different ways you can modify the build process.
|
||||
|
||||
To build additional targets, set the `targets` environment variable:
|
||||
|
||||
targets='mpw mpw-tests' ./build
|
||||
|
||||
To pass additional compiler arguments, eg. add a library search path, pass them as arguments to the script:
|
||||
|
||||
./build -L/usr/local/lib
|
||||
|
||||
There are a few toggleable features, to change them, pass them as environment variables:
|
||||
|
||||
mpw_color=0 ./build
|
||||
|
||||
Currently, there is only one toggleable feature:
|
||||
|
||||
- `mpw_color`: [default: 1] Colorized Identicon, depends on `ncurses-dev`.
|
||||
For detailed instructions, see [the native CLI instructions](platform-independent/cli-c/README.md).
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
#include "base64.h"
|
||||
|
||||
/* aaaack but it's fast and const should make it shared text page. */
|
||||
static const unsigned char b64ToBits[256] =
|
||||
static const uint8_t b64ToBits[256] =
|
||||
{
|
||||
/* ASCII table */
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
@@ -97,20 +97,20 @@ int mpw_base64_decode(uint8_t *plainBuf, const char *b64Text) {
|
||||
b64Cursor = (uint8_t *)b64Text;
|
||||
register uint8_t *plainCursor = plainBuf;
|
||||
while (b64Remaining > 4) {
|
||||
*(plainCursor++) = (b64ToBits[b64Cursor[0]] << 2 | b64ToBits[b64Cursor[1]] >> 4);
|
||||
*(plainCursor++) = (b64ToBits[b64Cursor[1]] << 4 | b64ToBits[b64Cursor[2]] >> 2);
|
||||
*(plainCursor++) = (b64ToBits[b64Cursor[2]] << 6 | b64ToBits[b64Cursor[3]]);
|
||||
*(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[0]] << 2 | b64ToBits[b64Cursor[1]] >> 4);
|
||||
*(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[1]] << 4 | b64ToBits[b64Cursor[2]] >> 2);
|
||||
*(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[2]] << 6 | b64ToBits[b64Cursor[3]]);
|
||||
b64Cursor += 4;
|
||||
b64Remaining -= 4;
|
||||
}
|
||||
|
||||
/* Note: (b64Size == 1) would be an error, so just ingore that case */
|
||||
if (b64Remaining > 1)
|
||||
*(plainCursor++) = (b64ToBits[b64Cursor[0]] << 2 | b64ToBits[b64Cursor[1]] >> 4);
|
||||
*(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[0]] << 2 | b64ToBits[b64Cursor[1]] >> 4);
|
||||
if (b64Remaining > 2)
|
||||
*(plainCursor++) = (b64ToBits[b64Cursor[1]] << 4 | b64ToBits[b64Cursor[2]] >> 2);
|
||||
*(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[1]] << 4 | b64ToBits[b64Cursor[2]] >> 2);
|
||||
if (b64Remaining > 3)
|
||||
*(plainCursor++) = (b64ToBits[b64Cursor[2]] << 6 | b64ToBits[b64Cursor[3]]);
|
||||
*(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[2]] << 6 | b64ToBits[b64Cursor[3]]);
|
||||
|
||||
return (int)(plainCursor - plainBuf);
|
||||
}
|
||||
@@ -126,7 +126,7 @@ size_t mpw_base64_encode_max(size_t plainSize) {
|
||||
|
||||
int mpw_base64_encode(char *b64Text, const uint8_t *plainBuf, size_t plainSize) {
|
||||
|
||||
int plainCursor = 0;
|
||||
size_t plainCursor = 0;
|
||||
char *b64Cursor = b64Text;
|
||||
for (; plainCursor < plainSize - 2; plainCursor += 3) {
|
||||
*b64Cursor++ = basis_64[((plainBuf[plainCursor] >> 2)) & 0x3F];
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
home=http://www.openwall.com/crypt/
|
||||
pkg=http://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz
|
||||
pkg_sha256=83fa01fca6996fe8d882b7f8e9ba0305a5664936100b01481ea3c6a8ce8d72fd
|
||||
patches=(arm)
|
||||
@@ -1,12 +0,0 @@
|
||||
--- x86.S 2014-11-21 09:09:58.000000000 -0500
|
||||
+++ x86.S 2014-11-21 09:11:01.000000000 -0500
|
||||
@@ -199,5 +199,9 @@
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
+#if defined(__arm__)
|
||||
+.section .note.GNU-stack,"",%progbits
|
||||
+#else
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
+#endif
|
||||
@@ -1,4 +0,0 @@
|
||||
home=http://www.tarsnap.com/scrypt.html
|
||||
git=https://github.com/Tarsnap/scrypt.git
|
||||
pkg=https://www.tarsnap.com/scrypt/scrypt-1.2.1.tgz
|
||||
pkg_sha256=4621f5e7da2f802e20850436219370092e9fcda93bd598f6d4236cce33f4c577
|
||||
@@ -1,38 +0,0 @@
|
||||
diff -ruN /Users/lhunath/.src/scrypt/Makefile ./Makefile
|
||||
--- /Users/lhunath/.src/scrypt/Makefile 2014-05-02 11:28:58.000000000 -0400
|
||||
+++ ./Makefile 2014-05-02 12:07:27.000000000 -0400
|
||||
@@ -2,11 +2,11 @@
|
||||
VER?= nosse
|
||||
SRCS= main.c
|
||||
LDADD+= -lcrypto
|
||||
-WARNS?= 6
|
||||
+WARNS?= 0
|
||||
|
||||
# We have a config file for FreeBSD
|
||||
CFLAGS += -I .
|
||||
-CFLAGS += -DCONFIG_H_FILE=\"config_freebsd.h\"
|
||||
+CFLAGS += -DCONFIG_H_FILE=\"config_osx.h\"
|
||||
|
||||
# Include all possible object files containing built scrypt code.
|
||||
CLEANFILES += crypto_scrypt-ref.o
|
||||
diff -ruN /Users/lhunath/.src/scrypt/lib/util/memlimit.c ./lib/util/memlimit.c
|
||||
--- /Users/lhunath/.src/scrypt/lib/util/memlimit.c 2014-05-02 11:28:58.000000000 -0400
|
||||
+++ ./lib/util/memlimit.c 2014-05-02 11:52:42.000000000 -0400
|
||||
@@ -75,7 +75,7 @@
|
||||
* have returned to us.
|
||||
*/
|
||||
if (usermemlen == sizeof(uint64_t))
|
||||
- usermem = *(uint64_t *)usermembuf;
|
||||
+ usermem = *(uint64_t *)(void *)usermembuf;
|
||||
else if (usermemlen == sizeof(uint32_t))
|
||||
usermem = SIZE_MAX;
|
||||
else
|
||||
diff -ruN /Users/lhunath/.src/scrypt/lib/util/memlimit.c ./lib/util/memlimit.c
|
||||
--- /Users/lhunath/.src/scrypt/config_osx.h 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ config_osx.h 2014-05-02 12:06:55.000000000 -0400
|
||||
@@ -0,0 +1,5 @@
|
||||
+/* A default configuration for FreeBSD, used if there is no config.h. */
|
||||
+
|
||||
+#define HAVE_POSIX_MEMALIGN 1
|
||||
+#define HAVE_SYSCTL_HW_USERMEM 1
|
||||
+#define HAVE_SYS_PARAM_H 1
|
||||
@@ -24,9 +24,14 @@
|
||||
|
||||
MPMasterKey mpw_masterKey(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
if (fullName && !strlen( fullName ))
|
||||
fullName = NULL;
|
||||
if (masterPassword && !strlen( masterPassword ))
|
||||
masterPassword = NULL;
|
||||
|
||||
trc( "-- mpw_masterKey (algorithm: %u)\n", algorithmVersion );
|
||||
trc( "fullName: %s\n", fullName );
|
||||
trc( "masterPassword.id: %s\n", mpw_id_buf( masterPassword, strlen( masterPassword ) ) );
|
||||
trc( "masterPassword.id: %s\n", masterPassword? mpw_id_buf( masterPassword, strlen( masterPassword ) ): NULL );
|
||||
if (!fullName || !masterPassword)
|
||||
return NULL;
|
||||
|
||||
@@ -49,6 +54,11 @@ MPSiteKey mpw_siteKey(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
if (siteName && !strlen( siteName ))
|
||||
siteName = NULL;
|
||||
if (keyContext && !strlen( keyContext ))
|
||||
keyContext = NULL;
|
||||
|
||||
trc( "-- mpw_siteKey (algorithm: %u)\n", algorithmVersion );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
@@ -78,7 +88,14 @@ const char *mpw_siteResult(
|
||||
const MPResultType resultType, const char *resultParam,
|
||||
const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
MPSiteKey siteKey = mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
||||
if (siteName && !strlen( siteName ))
|
||||
siteName = NULL;
|
||||
if (keyContext && !strlen( keyContext ))
|
||||
keyContext = NULL;
|
||||
if (resultParam && !strlen( resultParam ))
|
||||
resultParam = NULL;
|
||||
|
||||
MPSiteKey siteKey = mpw_siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext, algorithmVersion );
|
||||
if (!siteKey)
|
||||
return NULL;
|
||||
|
||||
@@ -102,7 +119,7 @@ const char *mpw_siteResult(
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (resultType & MPResultTypeClassState) {
|
||||
else if (resultType & MPResultTypeClassStateful) {
|
||||
switch (algorithmVersion) {
|
||||
case MPAlgorithmVersion0:
|
||||
return mpw_sitePasswordFromCrypt_v0( masterKey, siteKey, resultType, resultParam );
|
||||
@@ -142,28 +159,35 @@ const char *mpw_siteResult(
|
||||
const char *mpw_siteState(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext,
|
||||
const MPResultType resultType, const char *state,
|
||||
const MPResultType resultType, const char *resultParam,
|
||||
const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
if (siteName && !strlen( siteName ))
|
||||
siteName = NULL;
|
||||
if (keyContext && !strlen( keyContext ))
|
||||
keyContext = NULL;
|
||||
if (resultParam && !strlen( resultParam ))
|
||||
resultParam = NULL;
|
||||
|
||||
MPSiteKey siteKey = mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
||||
if (!siteKey)
|
||||
return NULL;
|
||||
|
||||
trc( "-- mpw_siteState (algorithm: %u)\n", algorithmVersion );
|
||||
trc( "resultType: %d (%s)\n", resultType, mpw_nameForType( resultType ) );
|
||||
trc( "state: %s\n", state );
|
||||
if (!masterKey || !state)
|
||||
trc( "resultParam: %s\n", resultParam );
|
||||
if (!masterKey || !resultParam)
|
||||
return NULL;
|
||||
|
||||
switch (algorithmVersion) {
|
||||
case MPAlgorithmVersion0:
|
||||
return mpw_siteState_v0( masterKey, siteKey, resultType, state );
|
||||
return mpw_siteState_v0( masterKey, siteKey, resultType, resultParam );
|
||||
case MPAlgorithmVersion1:
|
||||
return mpw_siteState_v1( masterKey, siteKey, resultType, state );
|
||||
return mpw_siteState_v1( masterKey, siteKey, resultType, resultParam );
|
||||
case MPAlgorithmVersion2:
|
||||
return mpw_siteState_v2( masterKey, siteKey, resultType, state );
|
||||
return mpw_siteState_v2( masterKey, siteKey, resultType, resultParam );
|
||||
case MPAlgorithmVersion3:
|
||||
return mpw_siteState_v3( masterKey, siteKey, resultType, state );
|
||||
return mpw_siteState_v3( masterKey, siteKey, resultType, resultParam );
|
||||
default:
|
||||
err( "Unsupported version: %d\n", algorithmVersion );
|
||||
return NULL;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#ifndef _MPW_ALGORITHM_H
|
||||
#define _MPW_ALGORITHM_H
|
||||
|
||||
typedef enum( unsigned int, MPAlgorithmVersion ) {
|
||||
typedef mpw_enum( unsigned int, MPAlgorithmVersion ) {
|
||||
/** V0 did math with chars whose signedness was platform-dependent. */
|
||||
MPAlgorithmVersion0,
|
||||
/** V1 miscounted the byte-length of multi-byte site names. */
|
||||
@@ -48,7 +48,8 @@ MPSiteKey mpw_siteKey(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
/** Encode a password for the site from the given site key.
|
||||
/** Generate a site result token from the given parameters.
|
||||
* @param resultParam A parameter for the resultType. For stateful result types, the output of mpw_siteState.
|
||||
* @return A newly allocated string or NULL if an error occurred. */
|
||||
const char *mpw_siteResult(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
@@ -56,12 +57,13 @@ const char *mpw_siteResult(
|
||||
const MPResultType resultType, const char *resultParam,
|
||||
const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
/** Perform symmetric encryption on a secret token's plainText.
|
||||
* @return The newly allocated cipherText of the secret token encrypted by the masterKey. */
|
||||
/** Encrypt a stateful site token for persistence.
|
||||
* @param resultParam A parameter for the resultType. For stateful result types, the desired mpw_siteResult.
|
||||
* @return A newly allocated string or NULL if an error occurred. */
|
||||
const char *mpw_siteState(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext,
|
||||
const MPResultType resultType, const char *state,
|
||||
const MPResultType resultType, const char *resultParam,
|
||||
const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
#endif // _MPW_ALGORITHM_H
|
||||
|
||||
@@ -18,33 +18,33 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
#include "base64.h"
|
||||
|
||||
#define MP_N 32768LU
|
||||
#define MP_r 8U
|
||||
#define MP_p 2U
|
||||
#define MP_otp_window 5 * 60 /* s */
|
||||
|
||||
// Algorithm version helpers.
|
||||
static const char *mpw_templateForType_v0(MPResultType type, uint16_t seedByte) {
|
||||
static const char *mpw_templateForType_v0(MPResultType type, uint16_t templateIndex) {
|
||||
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
char const *template = templates && count? templates[seedByte % count]: NULL;
|
||||
char const *template = templates && count? templates[templateIndex % count]: NULL;
|
||||
free( templates );
|
||||
return template;
|
||||
}
|
||||
|
||||
static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedByte) {
|
||||
static const char mpw_characterFromClass_v0(char characterClass, uint16_t classIndex) {
|
||||
|
||||
const char *classCharacters = mpw_charactersInClass( characterClass );
|
||||
if (!classCharacters)
|
||||
return '\0';
|
||||
|
||||
return classCharacters[seedByte % strlen( classCharacters )];
|
||||
return classCharacters[classIndex % strlen( classCharacters )];
|
||||
}
|
||||
|
||||
// Algorithm version overrides.
|
||||
@@ -56,11 +56,11 @@ static MPMasterKey mpw_masterKey_v0(
|
||||
|
||||
// Calculate the master key salt.
|
||||
trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s\n",
|
||||
keyScope, mpw_hex_l( htonl( mpw_utf8_strlen( fullName ) ) ), fullName );
|
||||
keyScope, mpw_hex_l( (uint32_t)mpw_utf8_strlen( fullName ) ), fullName );
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_push_string( &masterKeySalt, &masterKeySaltSize, keyScope );
|
||||
mpw_push_int( &masterKeySalt, &masterKeySaltSize, htonl( mpw_utf8_strlen( fullName ) ) );
|
||||
mpw_push_int( &masterKeySalt, &masterKeySaltSize, (uint32_t)mpw_utf8_strlen( fullName ) );
|
||||
mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
err( "Could not allocate master key salt: %s\n", strerror( errno ) );
|
||||
@@ -71,9 +71,9 @@ static MPMasterKey mpw_masterKey_v0(
|
||||
// Calculate the master key.
|
||||
trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", MP_N, MP_r, MP_p );
|
||||
MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
mpw_free( &masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
err( "Could not allocate master key: %s\n", strerror( errno ) );
|
||||
err( "Could not derive master key: %s\n", strerror( errno ) );
|
||||
return NULL;
|
||||
}
|
||||
trc( " => masterKey.id: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
@@ -82,31 +82,32 @@ static MPMasterKey mpw_masterKey_v0(
|
||||
}
|
||||
|
||||
static MPSiteKey mpw_siteKey_v0(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter,
|
||||
MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
|
||||
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
|
||||
trc( "keyScope: %s\n", keyScope );
|
||||
|
||||
// TODO: Implement MPCounterValueTOTP
|
||||
// OTP counter value.
|
||||
if (siteCounter == MPCounterValueTOTP)
|
||||
siteCounter = ((uint32_t)time( NULL ) / MP_otp_window) * MP_otp_window;
|
||||
|
||||
// Calculate the site seed.
|
||||
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
|
||||
keyScope, mpw_hex_l( htonl( mpw_utf8_strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),
|
||||
keyContext? mpw_hex_l( htonl( mpw_utf8_strlen( keyContext ) ) ): NULL, keyContext );
|
||||
keyScope, mpw_hex_l( (uint32_t)mpw_utf8_strlen( siteName ) ), siteName, mpw_hex_l( siteCounter ),
|
||||
keyContext? mpw_hex_l( (uint32_t)mpw_utf8_strlen( keyContext ) ): NULL, keyContext );
|
||||
size_t siteSaltSize = 0;
|
||||
uint8_t *siteSalt = NULL;
|
||||
mpw_push_string( &siteSalt, &siteSaltSize, keyScope );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( siteName ) ) );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)mpw_utf8_strlen( siteName ) );
|
||||
mpw_push_string( &siteSalt, &siteSaltSize, siteName );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, siteCounter );
|
||||
if (keyContext) {
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( keyContext ) ) );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)mpw_utf8_strlen( keyContext ) );
|
||||
mpw_push_string( &siteSalt, &siteSaltSize, keyContext );
|
||||
}
|
||||
if (!siteSalt || !siteSaltSize) {
|
||||
if (!siteSalt) {
|
||||
err( "Could not allocate site salt: %s\n", strerror( errno ) );
|
||||
mpw_free( siteSalt, siteSaltSize );
|
||||
return NULL;
|
||||
}
|
||||
trc( " => siteSalt.id: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) );
|
||||
@@ -114,7 +115,7 @@ static MPSiteKey mpw_siteKey_v0(
|
||||
trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n",
|
||||
mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
|
||||
mpw_free( siteSalt, siteSaltSize );
|
||||
mpw_free( &siteSalt, siteSaltSize );
|
||||
if (!siteKey) {
|
||||
err( "Could not derive site key: %s\n", strerror( errno ) );
|
||||
return NULL;
|
||||
@@ -125,12 +126,15 @@ static MPSiteKey mpw_siteKey_v0(
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromTemplate_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey __unused masterKey, MPSiteKey siteKey, MPResultType resultType, const char __unused *resultParam) {
|
||||
|
||||
const char *_siteKey = (const char *)siteKey;
|
||||
|
||||
// Determine the template.
|
||||
const char *_siteKey = (const char *)siteKey;
|
||||
const char *template = mpw_templateForType_v0( resultType, htons( _siteKey[0] ) );
|
||||
trc( "template: %u => %s\n", htons( _siteKey[0] ), template );
|
||||
uint16_t seedByte;
|
||||
mpw_uint16( (uint16_t)_siteKey[0], (uint8_t *)&seedByte );
|
||||
const char *template = mpw_templateForType_v0( resultType, seedByte );
|
||||
trc( "template: %u => %s\n", seedByte, template );
|
||||
if (!template)
|
||||
return NULL;
|
||||
if (strlen( template ) > MPSiteKeySize) {
|
||||
@@ -139,11 +143,12 @@ static const char *mpw_sitePasswordFromTemplate_v0(
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass_v0( template[c], htons( _siteKey[c + 1] ) );
|
||||
mpw_uint16( (uint16_t)_siteKey[c + 1], (uint8_t *)&seedByte );
|
||||
sitePassword[c] = mpw_characterFromClass_v0( template[c], seedByte );
|
||||
trc( " - class: %c, index: %5u (0x%02hX) => character: %c\n",
|
||||
template[c], htons( _siteKey[c + 1] ), htons( _siteKey[c + 1] ), sitePassword[c] );
|
||||
template[c], seedByte, seedByte, sitePassword[c] );
|
||||
}
|
||||
trc( " => password: %s\n", sitePassword );
|
||||
|
||||
@@ -151,7 +156,7 @@ static const char *mpw_sitePasswordFromTemplate_v0(
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromCrypt_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
|
||||
MPMasterKey masterKey, MPSiteKey __unused siteKey, MPResultType __unused resultType, const char *cipherText) {
|
||||
|
||||
if (!cipherText) {
|
||||
err( "Missing encrypted state.\n" );
|
||||
@@ -163,25 +168,25 @@ static const char *mpw_sitePasswordFromCrypt_v0(
|
||||
size_t bufSize = (size_t)mpw_base64_decode( cipherBuf, cipherText );
|
||||
if ((int)bufSize < 0) {
|
||||
err( "Base64 decoding error." );
|
||||
mpw_free( cipherBuf, mpw_base64_decode_max( cipherText ) );
|
||||
mpw_free( &cipherBuf, mpw_base64_decode_max( cipherText ) );
|
||||
return NULL;
|
||||
}
|
||||
trc( "b64 decoded: %zu bytes = %s\n", bufSize, mpw_hex( cipherBuf, bufSize ) );
|
||||
|
||||
// Decrypt
|
||||
const uint8_t *plainBytes = mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize );
|
||||
mpw_free( &cipherBuf, bufSize );
|
||||
const char *plainText = strndup( (char *)plainBytes, bufSize );
|
||||
mpw_free( plainBytes, bufSize );
|
||||
mpw_free( &plainBytes, bufSize );
|
||||
if (!plainText)
|
||||
err( "AES decryption error: %s\n", strerror( errno ) );
|
||||
trc( "decrypted -> plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) );
|
||||
mpw_free( cipherBuf, bufSize );
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromDerive_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey __unused masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) {
|
||||
|
||||
switch (resultType) {
|
||||
case MPResultTypeDeriveKey: {
|
||||
@@ -206,15 +211,16 @@ static const char *mpw_sitePasswordFromDerive_v0(
|
||||
|
||||
// Base64-encode
|
||||
size_t b64Max = mpw_base64_encode_max( keySize );
|
||||
char *sitePassword = calloc( 1, b64Max + 1 );
|
||||
if (mpw_base64_encode( sitePassword, resultKey, keySize ) < 0) {
|
||||
char *b64Key = calloc( 1, b64Max + 1 );
|
||||
if (mpw_base64_encode( b64Key, resultKey, keySize ) < 0) {
|
||||
err( "Base64 encoding error." );
|
||||
mpw_free_string( sitePassword );
|
||||
sitePassword = NULL;
|
||||
mpw_free_string( &b64Key );
|
||||
}
|
||||
trc( "b64 encoded -> key.id: %s\n", mpw_id_buf( sitePassword, strlen( sitePassword ) ) );
|
||||
else
|
||||
trc( "b64 encoded -> key.id: %s\n", mpw_id_buf( b64Key, strlen( b64Key ) ) );
|
||||
mpw_free( &resultKey, keySize );
|
||||
|
||||
return sitePassword;
|
||||
return b64Key;
|
||||
}
|
||||
default:
|
||||
err( "Unsupported derived password type: %d\n", resultType );
|
||||
@@ -223,7 +229,7 @@ static const char *mpw_sitePasswordFromDerive_v0(
|
||||
}
|
||||
|
||||
static const char *mpw_siteState_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *plainText) {
|
||||
MPMasterKey masterKey, MPSiteKey __unused siteKey, MPResultType __unused resultType, const char *plainText) {
|
||||
|
||||
// Encrypt
|
||||
size_t bufSize = strlen( plainText );
|
||||
@@ -239,11 +245,11 @@ static const char *mpw_siteState_v0(
|
||||
char *cipherText = calloc( 1, b64Max + 1 );
|
||||
if (mpw_base64_encode( cipherText, cipherBuf, bufSize ) < 0) {
|
||||
err( "Base64 encoding error." );
|
||||
mpw_free_string( cipherText );
|
||||
cipherText = NULL;
|
||||
mpw_free_string( &cipherText );
|
||||
}
|
||||
else
|
||||
trc( "b64 encoded -> cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) );
|
||||
mpw_free( cipherBuf, bufSize );
|
||||
mpw_free( &cipherBuf, bufSize );
|
||||
|
||||
return cipherText;
|
||||
}
|
||||
|
||||
@@ -17,28 +17,26 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768LU
|
||||
#define MP_r 8U
|
||||
#define MP_p 2U
|
||||
#define MP_otp_window 5 * 60 /* s */
|
||||
|
||||
// Inherited functions.
|
||||
MPMasterKey mpw_masterKey_v0(
|
||||
const char *fullName, const char *masterPassword);
|
||||
MPSiteKey mpw_siteKey_v0(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext);
|
||||
MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter,
|
||||
MPKeyPurpose keyPurpose, const char *keyContext);
|
||||
const char *mpw_sitePasswordFromCrypt_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText);
|
||||
const char *mpw_sitePasswordFromDerive_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam);
|
||||
const char *mpw_siteState_v0(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state);
|
||||
|
||||
// Algorithm version overrides.
|
||||
static MPMasterKey mpw_masterKey_v1(
|
||||
@@ -48,18 +46,19 @@ static MPMasterKey mpw_masterKey_v1(
|
||||
}
|
||||
|
||||
static MPSiteKey mpw_siteKey_v1(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter,
|
||||
MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
|
||||
return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromTemplate_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey __unused masterKey, MPSiteKey siteKey, MPResultType resultType, const char __unused *resultParam) {
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( resultType, siteKey[0] );
|
||||
trc( "template: %u => %s\n", siteKey[0], template );
|
||||
uint8_t seedByte = siteKey[0];
|
||||
const char *template = mpw_templateForType( resultType, seedByte );
|
||||
trc( "template: %u => %s\n", seedByte, template );
|
||||
if (!template)
|
||||
return NULL;
|
||||
if (strlen( template ) > MPSiteKeySize) {
|
||||
@@ -70,9 +69,10 @@ static const char *mpw_sitePasswordFromTemplate_v1(
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], siteKey[c + 1] );
|
||||
seedByte = siteKey[c + 1];
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], seedByte );
|
||||
trc( " - class: %c, index: %3u (0x%02hhX) => character: %c\n",
|
||||
template[c], siteKey[c + 1], siteKey[c + 1], sitePassword[c] );
|
||||
template[c], seedByte, seedByte, sitePassword[c] );
|
||||
}
|
||||
trc( " => password: %s\n", sitePassword );
|
||||
|
||||
@@ -80,19 +80,19 @@ static const char *mpw_sitePasswordFromTemplate_v1(
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromCrypt_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText) {
|
||||
|
||||
return mpw_sitePasswordFromCrypt_v0( masterKey, siteKey, resultType, cipherText );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromDerive_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) {
|
||||
|
||||
return mpw_sitePasswordFromDerive_v0( masterKey, siteKey, resultType, resultParam );
|
||||
}
|
||||
|
||||
static const char *mpw_siteState_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state) {
|
||||
|
||||
return mpw_siteState_v0( masterKey, siteKey, resultType, state );
|
||||
}
|
||||
|
||||
@@ -18,26 +18,26 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768LU
|
||||
#define MP_r 8U
|
||||
#define MP_p 2U
|
||||
#define MP_otp_window 5 * 60 /* s */
|
||||
|
||||
// Inherited functions.
|
||||
MPMasterKey mpw_masterKey_v1(
|
||||
const char *fullName, const char *masterPassword);
|
||||
const char *mpw_sitePasswordFromTemplate_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam);
|
||||
const char *mpw_sitePasswordFromCrypt_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText);
|
||||
const char *mpw_sitePasswordFromDerive_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam);
|
||||
const char *mpw_siteState_v1(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state);
|
||||
|
||||
// Algorithm version overrides.
|
||||
static MPMasterKey mpw_masterKey_v2(
|
||||
@@ -47,31 +47,32 @@ static MPMasterKey mpw_masterKey_v2(
|
||||
}
|
||||
|
||||
static MPSiteKey mpw_siteKey_v2(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter,
|
||||
MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
|
||||
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
|
||||
trc( "keyScope: %s\n", keyScope );
|
||||
|
||||
// TODO: Implement MPCounterValueTOTP
|
||||
// OTP counter value.
|
||||
if (siteCounter == MPCounterValueTOTP)
|
||||
siteCounter = ((uint32_t)time( NULL ) / MP_otp_window) * MP_otp_window;
|
||||
|
||||
// Calculate the site seed.
|
||||
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
|
||||
keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),
|
||||
keyContext? mpw_hex_l( htonl( strlen( keyContext ) ) ): NULL, keyContext );
|
||||
keyScope, mpw_hex_l( (uint32_t)strlen( siteName ) ), siteName, mpw_hex_l( siteCounter ),
|
||||
keyContext? mpw_hex_l( (uint32_t)strlen( keyContext ) ): NULL, keyContext );
|
||||
size_t siteSaltSize = 0;
|
||||
uint8_t *siteSalt = NULL;
|
||||
mpw_push_string( &siteSalt, &siteSaltSize, keyScope );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( siteName ) ) );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)strlen( siteName ) );
|
||||
mpw_push_string( &siteSalt, &siteSaltSize, siteName );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, siteCounter );
|
||||
if (keyContext) {
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( keyContext ) ) );
|
||||
mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)strlen( keyContext ) );
|
||||
mpw_push_string( &siteSalt, &siteSaltSize, keyContext );
|
||||
}
|
||||
if (!siteSalt || !siteSaltSize) {
|
||||
if (!siteSalt) {
|
||||
err( "Could not allocate site salt: %s\n", strerror( errno ) );
|
||||
mpw_free( siteSalt, siteSaltSize );
|
||||
return NULL;
|
||||
}
|
||||
trc( " => siteSalt.id: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) );
|
||||
@@ -79,9 +80,9 @@ static MPSiteKey mpw_siteKey_v2(
|
||||
trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n",
|
||||
mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
|
||||
mpw_free( siteSalt, siteSaltSize );
|
||||
mpw_free( &siteSalt, siteSaltSize );
|
||||
if (!siteKey) {
|
||||
err( "Could not allocate site key: %s\n", strerror( errno ) );
|
||||
err( "Could not derive site key: %s\n", strerror( errno ) );
|
||||
return NULL;
|
||||
}
|
||||
trc( " => siteKey.id: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
|
||||
@@ -90,25 +91,25 @@ static MPSiteKey mpw_siteKey_v2(
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromTemplate_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) {
|
||||
|
||||
return mpw_sitePasswordFromTemplate_v1( masterKey, siteKey, resultType, resultParam );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromCrypt_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText) {
|
||||
|
||||
return mpw_sitePasswordFromCrypt_v1( masterKey, siteKey, resultType, cipherText );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromDerive_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) {
|
||||
|
||||
return mpw_sitePasswordFromDerive_v1( masterKey, siteKey, resultType, resultParam );
|
||||
}
|
||||
|
||||
static const char *mpw_siteState_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state) {
|
||||
|
||||
return mpw_siteState_v1( masterKey, siteKey, resultType, state );
|
||||
}
|
||||
|
||||
@@ -18,27 +18,26 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768LU
|
||||
#define MP_r 8U
|
||||
#define MP_p 2U
|
||||
#define MP_otp_window 5 * 60 /* s */
|
||||
|
||||
// Inherited functions.
|
||||
MPSiteKey mpw_siteKey_v2(
|
||||
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext);
|
||||
MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter,
|
||||
MPKeyPurpose keyPurpose, const char *keyContext);
|
||||
const char *mpw_sitePasswordFromTemplate_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam);
|
||||
const char *mpw_sitePasswordFromCrypt_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText);
|
||||
const char *mpw_sitePasswordFromDerive_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam);
|
||||
const char *mpw_siteState_v2(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state);
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state);
|
||||
|
||||
// Algorithm version overrides.
|
||||
static MPMasterKey mpw_masterKey_v3(
|
||||
@@ -49,11 +48,11 @@ static MPMasterKey mpw_masterKey_v3(
|
||||
|
||||
// Calculate the master key salt.
|
||||
trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s\n",
|
||||
keyScope, mpw_hex_l( htonl( strlen( fullName ) ) ), fullName );
|
||||
keyScope, mpw_hex_l( (uint32_t)strlen( fullName ) ), fullName );
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_push_string( &masterKeySalt, &masterKeySaltSize, keyScope );
|
||||
mpw_push_int( &masterKeySalt, &masterKeySaltSize, htonl( strlen( fullName ) ) );
|
||||
mpw_push_int( &masterKeySalt, &masterKeySaltSize, (uint32_t)strlen( fullName ) );
|
||||
mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
err( "Could not allocate master key salt: %s\n", strerror( errno ) );
|
||||
@@ -64,9 +63,9 @@ static MPMasterKey mpw_masterKey_v3(
|
||||
// Calculate the master key.
|
||||
trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", MP_N, MP_r, MP_p );
|
||||
MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
mpw_free( &masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
err( "Could not allocate master key: %s\n", strerror( errno ) );
|
||||
err( "Could not derive master key: %s\n", strerror( errno ) );
|
||||
return NULL;
|
||||
}
|
||||
trc( " => masterKey.id: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) );
|
||||
@@ -75,32 +74,32 @@ static MPMasterKey mpw_masterKey_v3(
|
||||
}
|
||||
|
||||
static MPSiteKey mpw_siteKey_v3(
|
||||
const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
|
||||
const MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter,
|
||||
MPKeyPurpose keyPurpose, const char *keyContext) {
|
||||
|
||||
return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromTemplate_v3(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) {
|
||||
|
||||
return mpw_sitePasswordFromTemplate_v2( masterKey, siteKey, resultType, resultParam );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromCrypt_v3(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText) {
|
||||
|
||||
return mpw_sitePasswordFromCrypt_v2( masterKey, siteKey, resultType, cipherText );
|
||||
}
|
||||
|
||||
static const char *mpw_sitePasswordFromDerive_v3(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) {
|
||||
|
||||
return mpw_sitePasswordFromDerive_v2( masterKey, siteKey, resultType, resultParam );
|
||||
}
|
||||
|
||||
static const char *mpw_siteState_v3(
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state) {
|
||||
MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state) {
|
||||
|
||||
return mpw_siteState_v2( masterKey, siteKey, resultType, state );
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "mpw-marshall-util.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
char *mpw_get_token(char **in, char *eol, char *delim) {
|
||||
char *mpw_get_token(const char **in, const char *eol, char *delim) {
|
||||
|
||||
// Skip leading spaces.
|
||||
for (; **in == ' '; ++*in);
|
||||
@@ -50,6 +50,7 @@ time_t mpw_mktime(
|
||||
return false;
|
||||
}
|
||||
|
||||
#if MPW_JSON
|
||||
json_object *mpw_get_json_section(
|
||||
json_object *obj, const char *section) {
|
||||
|
||||
@@ -76,14 +77,14 @@ const char *mpw_get_json_string(
|
||||
return json_object_get_string( json_value );
|
||||
}
|
||||
|
||||
int32_t mpw_get_json_int(
|
||||
json_object *obj, const char *section, int32_t defaultValue) {
|
||||
int64_t mpw_get_json_int(
|
||||
json_object *obj, const char *section, int64_t defaultValue) {
|
||||
|
||||
json_object *json_value = mpw_get_json_section( obj, section );
|
||||
if (!json_value)
|
||||
return defaultValue;
|
||||
|
||||
return json_object_get_int( json_value );
|
||||
return json_object_get_int64( json_value );
|
||||
}
|
||||
|
||||
bool mpw_get_json_boolean(
|
||||
@@ -95,15 +96,15 @@ bool mpw_get_json_boolean(
|
||||
|
||||
return json_object_get_boolean( json_value ) == TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool mpw_update_masterKey(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm,
|
||||
const char *fullName, const char *masterPassword) {
|
||||
|
||||
if (*masterKeyAlgorithm != targetKeyAlgorithm) {
|
||||
mpw_free( *masterKey, MPMasterKeySize );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
*masterKeyAlgorithm = targetKeyAlgorithm;
|
||||
*masterKey = mpw_masterKey(
|
||||
fullName, masterPassword, *masterKeyAlgorithm );
|
||||
*masterKey = mpw_masterKey( fullName, masterPassword, *masterKeyAlgorithm );
|
||||
if (!*masterKey) {
|
||||
err( "Couldn't derive master key for user %s, algorithm %d.\n", fullName, *masterKeyAlgorithm );
|
||||
return false;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define _MPW_MARSHALL_UTIL_H
|
||||
|
||||
#include <time.h>
|
||||
#include <json-c/json.h>
|
||||
#include "json-c/json.h"
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
* The input string reference is advanced beyond the token delimitor if one is found.
|
||||
* @return A new string containing the token or NULL if the delim wasn't found before eol. */
|
||||
char *mpw_get_token(
|
||||
char **in, char *eol, char *delim);
|
||||
const char **in, const char *eol, char *delim);
|
||||
/** Convert an RFC 3339 time string into epoch time. */
|
||||
time_t mpw_mktime(
|
||||
const char *time);
|
||||
@@ -50,8 +50,8 @@ const char *mpw_get_json_string(
|
||||
/** Search for an integer in a JSON object tree.
|
||||
* @param section A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return The integer value or defaultValue if one of the section's object keys was not found in the source object's tree. */
|
||||
int32_t mpw_get_json_int(
|
||||
json_object *obj, const char *section, int32_t defaultValue);
|
||||
int64_t mpw_get_json_int(
|
||||
json_object *obj, const char *section, int64_t defaultValue);
|
||||
/** Search for a boolean in a JSON object tree.
|
||||
* @param section A dot-delimited list of JSON object keys to walk toward the child object.
|
||||
* @return The boolean value or defaultValue if one of the section's object keys was not found in the source object's tree. */
|
||||
|
||||
@@ -63,8 +63,8 @@ MPMarshalledSite *mpw_marshall_site(
|
||||
.counter = siteCounter,
|
||||
.algorithm = algorithmVersion,
|
||||
|
||||
.loginName = NULL,
|
||||
.loginGenerated = false,
|
||||
.loginContent = NULL,
|
||||
.loginType = MPResultTypeTemplateName,
|
||||
|
||||
.url = NULL,
|
||||
.uses = 0,
|
||||
@@ -79,35 +79,54 @@ MPMarshalledSite *mpw_marshall_site(
|
||||
MPMarshalledQuestion *mpw_marshal_question(
|
||||
MPMarshalledSite *site, const char *keyword) {
|
||||
|
||||
if (!keyword || !mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count ))
|
||||
if (!mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count ))
|
||||
return NULL;
|
||||
if (!keyword)
|
||||
keyword = "";
|
||||
|
||||
MPMarshalledQuestion *question = &site->questions[site->questions_count - 1];
|
||||
*question = (MPMarshalledQuestion){
|
||||
.keyword = strdup( keyword ),
|
||||
.content = NULL,
|
||||
.type = MPResultTypeTemplatePhrase,
|
||||
};
|
||||
return question;
|
||||
}
|
||||
|
||||
bool mpw_marshal_free(
|
||||
MPMarshalledUser *user) {
|
||||
bool mpw_marshal_info_free(
|
||||
MPMarshallInfo **info) {
|
||||
|
||||
if (!user)
|
||||
if (!info || !*info)
|
||||
return true;
|
||||
|
||||
bool success = true;
|
||||
for (size_t s = 0; s < user->sites_count; ++s) {
|
||||
MPMarshalledSite *site = &user->sites[s];
|
||||
success &= mpw_free_string( site->name );
|
||||
success &= mpw_free_strings( &(*info)->fullName, &(*info)->keyID, NULL );
|
||||
success &= mpw_free( info, sizeof( MPMarshallInfo ) );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool mpw_marshal_free(
|
||||
MPMarshalledUser **user) {
|
||||
|
||||
if (!user || !*user)
|
||||
return true;
|
||||
|
||||
bool success = true;
|
||||
success &= mpw_free_strings( &(*user)->fullName, &(*user)->masterPassword, NULL );
|
||||
|
||||
for (size_t s = 0; s < (*user)->sites_count; ++s) {
|
||||
MPMarshalledSite *site = &(*user)->sites[s];
|
||||
success &= mpw_free_strings( &site->name, &site->content, &site->loginContent, &site->url, NULL );
|
||||
|
||||
for (size_t q = 0; q < site->questions_count; ++q) {
|
||||
MPMarshalledQuestion *question = &site->questions[q];
|
||||
success &= mpw_free_string( question->keyword );
|
||||
success &= mpw_free_strings( &question->keyword, &question->content, NULL );
|
||||
}
|
||||
success &= mpw_free( site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count );
|
||||
success &= mpw_free( &site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count );
|
||||
}
|
||||
success &= mpw_free( user->sites, sizeof( MPMarshalledSite ) * user->sites_count );
|
||||
success &= mpw_free_string( user->fullName );
|
||||
success &= mpw_free_string( user->masterPassword );
|
||||
|
||||
success &= mpw_free( &(*user)->sites, sizeof( MPMarshalledSite ) * (*user)->sites_count );
|
||||
success &= mpw_free( user, sizeof( MPMarshalledUser ) );
|
||||
|
||||
return success;
|
||||
@@ -163,7 +182,7 @@ static bool mpw_marshall_write_flat(
|
||||
if (!site->name || !strlen( site->name ))
|
||||
continue;
|
||||
|
||||
const char *content = NULL;
|
||||
const char *content = NULL, *loginContent = NULL;
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, user->fullName, user->masterPassword )) {
|
||||
@@ -171,26 +190,32 @@ static bool mpw_marshall_write_flat(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (site->type & MPResultTypeClassTemplate)
|
||||
content = mpw_siteResult( masterKey, site->name, site->counter,
|
||||
MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm );
|
||||
loginContent = mpw_siteResult( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeIdentification, NULL, site->loginType, site->loginContent, site->algorithm );
|
||||
}
|
||||
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
|
||||
else {
|
||||
// Redacted
|
||||
if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
|
||||
content = strdup( site->content );
|
||||
if (site->loginType & MPSiteFeatureExportContent && site->loginContent && strlen( site->loginContent ))
|
||||
loginContent = strdup( site->loginContent );
|
||||
}
|
||||
|
||||
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",
|
||||
dateString, (long)site->uses, (long)site->type, (long)site->algorithm, (long)site->counter,
|
||||
site->loginName?: "", site->name, content?: "" );
|
||||
mpw_free_string( content );
|
||||
loginContent?: "", site->name, content?: "" );
|
||||
mpw_free_strings( &content, &loginContent, NULL );
|
||||
}
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
mpw_free( &masterKey, MPMasterKeySize );
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallSuccess };
|
||||
*error = (MPMarshallError){ .type = MPMarshallSuccess };
|
||||
return true;
|
||||
}
|
||||
|
||||
#if MPW_JSON
|
||||
static bool mpw_marshall_write_json(
|
||||
char **out, const MPMarshalledUser *user, MPMarshallError *error) {
|
||||
|
||||
@@ -225,15 +250,15 @@ static bool mpw_marshall_write_json(
|
||||
// Section: "user"
|
||||
json_object *json_user = json_object_new_object();
|
||||
json_object_object_add( json_file, "user", json_user );
|
||||
json_object_object_add( json_user, "avatar", json_object_new_int( (int)user->avatar ) );
|
||||
json_object_object_add( json_user, "avatar", json_object_new_int( (int32_t)user->avatar ) );
|
||||
json_object_object_add( json_user, "full_name", json_object_new_string( user->fullName ) );
|
||||
|
||||
if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &user->lastUsed ) ))
|
||||
json_object_object_add( json_user, "last_used", json_object_new_string( dateString ) );
|
||||
json_object_object_add( json_user, "key_id", json_object_new_string( mpw_id_buf( masterKey, MPMasterKeySize ) ) );
|
||||
|
||||
json_object_object_add( json_user, "algorithm", json_object_new_int( (int)user->algorithm ) );
|
||||
json_object_object_add( json_user, "default_type", json_object_new_int( (int)user->defaultType ) );
|
||||
json_object_object_add( json_user, "algorithm", json_object_new_int( (int32_t)user->algorithm ) );
|
||||
json_object_object_add( json_user, "default_type", json_object_new_int( (int32_t)user->defaultType ) );
|
||||
|
||||
// Section "sites"
|
||||
json_object *json_sites = json_object_new_object();
|
||||
@@ -243,7 +268,7 @@ static bool mpw_marshall_write_json(
|
||||
if (!site->name || !strlen( site->name ))
|
||||
continue;
|
||||
|
||||
const char *content = NULL;
|
||||
const char *content = NULL, *loginContent = NULL;
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, user->fullName, user->masterPassword )) {
|
||||
@@ -251,26 +276,31 @@ static bool mpw_marshall_write_json(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (site->type & MPResultTypeClassTemplate)
|
||||
content = mpw_siteResult( masterKey, site->name, site->counter,
|
||||
MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm );
|
||||
loginContent = mpw_siteResult( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeIdentification, NULL, site->loginType, site->loginContent, site->algorithm );
|
||||
}
|
||||
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
|
||||
else {
|
||||
// Redacted
|
||||
if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
|
||||
content = strdup( site->content );
|
||||
if (site->loginType & MPSiteFeatureExportContent && site->loginContent && strlen( site->loginContent ))
|
||||
loginContent = strdup( site->loginContent );
|
||||
}
|
||||
|
||||
json_object *json_site = json_object_new_object();
|
||||
json_object_object_add( json_sites, site->name, json_site );
|
||||
json_object_object_add( json_site, "type", json_object_new_int( (int)site->type ) );
|
||||
json_object_object_add( json_site, "counter", json_object_new_int( (int)site->counter ) );
|
||||
json_object_object_add( json_site, "algorithm", json_object_new_int( (int)site->algorithm ) );
|
||||
json_object_object_add( json_site, "type", json_object_new_int( (int32_t)site->type ) );
|
||||
json_object_object_add( json_site, "counter", json_object_new_int( (int32_t)site->counter ) );
|
||||
json_object_object_add( json_site, "algorithm", json_object_new_int( (int32_t)site->algorithm ) );
|
||||
if (content)
|
||||
json_object_object_add( json_site, "password", json_object_new_string( content ) );
|
||||
if (site->loginName)
|
||||
json_object_object_add( json_site, "login_name", json_object_new_string( site->loginName ) );
|
||||
json_object_object_add( json_site, "login_generated", json_object_new_boolean( site->loginGenerated ) );
|
||||
if (loginContent)
|
||||
json_object_object_add( json_site, "login_name", json_object_new_string( loginContent ) );
|
||||
json_object_object_add( json_site, "login_type", json_object_new_int( (int32_t)site->loginType ) );
|
||||
|
||||
json_object_object_add( json_site, "uses", json_object_new_int( (int)site->uses ) );
|
||||
json_object_object_add( json_site, "uses", json_object_new_int( (int32_t)site->uses ) );
|
||||
if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) ))
|
||||
json_object_object_add( json_site, "last_used", json_object_new_string( dateString ) );
|
||||
|
||||
@@ -283,13 +313,18 @@ static bool mpw_marshall_write_json(
|
||||
|
||||
json_object *json_site_question = json_object_new_object();
|
||||
json_object_object_add( json_site_questions, question->keyword, json_site_question );
|
||||
json_object_object_add( json_site_question, "type", json_object_new_int( (int32_t)question->type ) );
|
||||
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
const char *answer = mpw_siteResult( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeRecovery, question->keyword, MPResultTypeTemplatePhrase, NULL, site->algorithm );
|
||||
if (answer)
|
||||
json_object_object_add( json_site_question, "answer", json_object_new_string( answer ) );
|
||||
const char *answerContent = mpw_siteResult( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeRecovery, question->keyword, question->type, question->content, site->algorithm );
|
||||
json_object_object_add( json_site_question, "answer", json_object_new_string( answerContent ) );
|
||||
}
|
||||
else {
|
||||
// Redacted
|
||||
if (site->type & MPSiteFeatureExportContent && question->content && strlen( question->content ))
|
||||
json_object_object_add( json_site_question, "answer", json_object_new_string( question->content ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,35 +333,93 @@ static bool mpw_marshall_write_json(
|
||||
if (site->url)
|
||||
json_object_object_add( json_site_mpw, "url", json_object_new_string( site->url ) );
|
||||
|
||||
mpw_free_string( content );
|
||||
mpw_free_strings( &content, &loginContent, NULL );
|
||||
}
|
||||
|
||||
mpw_string_pushf( out, "%s\n", json_object_to_json_string_ext( json_file, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED ) );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
mpw_free( &masterKey, MPMasterKeySize );
|
||||
json_object_put( json_file );
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallSuccess };
|
||||
*error = (MPMarshallError){ .type = MPMarshallSuccess };
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool mpw_marshall_write(
|
||||
char **out, const MPMarshallFormat outFormat, const MPMarshalledUser *user, MPMarshallError *error) {
|
||||
|
||||
switch (outFormat) {
|
||||
case MPMarshallFormatNone:
|
||||
*error = (MPMarshallError){ .type = MPMarshallSuccess };
|
||||
return false;
|
||||
case MPMarshallFormatFlat:
|
||||
return mpw_marshall_write_flat( out, user, error );
|
||||
#if MPW_JSON
|
||||
case MPMarshallFormatJSON:
|
||||
return mpw_marshall_write_json( out, user, error );
|
||||
#endif
|
||||
default:
|
||||
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) };
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void mpw_marshall_read_flat_info(
|
||||
const char *in, MPMarshallInfo *info) {
|
||||
|
||||
info->algorithm = MPAlgorithmVersionCurrent;
|
||||
|
||||
// Parse import data.
|
||||
bool headerStarted = false;
|
||||
for (const char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) {
|
||||
|
||||
// Comment or header
|
||||
if (*positionInLine == '#') {
|
||||
++positionInLine;
|
||||
|
||||
if (!headerStarted) {
|
||||
if (*positionInLine == '#')
|
||||
// ## starts header
|
||||
headerStarted = true;
|
||||
// Comment before header
|
||||
continue;
|
||||
}
|
||||
if (*positionInLine == '#')
|
||||
// ## ends header
|
||||
break;
|
||||
|
||||
// Header
|
||||
char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" );
|
||||
char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" );
|
||||
if (!headerName || !headerValue)
|
||||
continue;
|
||||
|
||||
if (strcmp( headerName, "Algorithm" ) == 0)
|
||||
info->algorithm = (MPAlgorithmVersion)atoi( headerValue );
|
||||
if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0)
|
||||
info->fullName = strdup( headerValue );
|
||||
if (strcmp( headerName, "Key ID" ) == 0)
|
||||
info->keyID = strdup( headerValue );
|
||||
if (strcmp( headerName, "Passwords" ) == 0)
|
||||
info->redacted = strcmp( headerValue, "VISIBLE" ) != 0;
|
||||
if (strcmp( headerName, "Date" ) == 0)
|
||||
info->date = mpw_mktime( headerValue );
|
||||
|
||||
mpw_free_strings( &headerName, &headerValue, NULL );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
char *in, const char *masterPassword, MPMarshallError *error) {
|
||||
const char *in, const char *masterPassword, MPMarshallError *error) {
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal, "Unexpected internal error." };
|
||||
if (!in || !strlen( in )) {
|
||||
error->type = MPMarshallErrorStructure;
|
||||
error->description = mpw_str( "No input data." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Parse import data.
|
||||
MPMasterKey masterKey = NULL;
|
||||
@@ -336,7 +429,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1;
|
||||
MPResultType defaultType = MPResultTypeDefault;
|
||||
bool headerStarted = false, headerEnded = false, importRedacted = false;
|
||||
for (char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) {
|
||||
for (const char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) {
|
||||
|
||||
// Comment or header
|
||||
if (*positionInLine == '#') {
|
||||
@@ -394,8 +487,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
if (strcmp( headerName, "Passwords" ) == 0)
|
||||
importRedacted = strcmp( headerValue, "VISIBLE" ) != 0;
|
||||
|
||||
mpw_free_string( headerName );
|
||||
mpw_free_string( headerValue );
|
||||
mpw_free_strings( &headerName, &headerValue, NULL );
|
||||
continue;
|
||||
}
|
||||
if (!headerEnded)
|
||||
@@ -437,7 +529,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
if (typeAndVersion) {
|
||||
str_type = strdup( strtok( typeAndVersion, ":" ) );
|
||||
str_algorithm = strdup( strtok( NULL, "" ) );
|
||||
mpw_free_string( typeAndVersion );
|
||||
mpw_free_string( &typeAndVersion );
|
||||
}
|
||||
str_counter = strdup( "1" );
|
||||
siteLoginName = NULL;
|
||||
@@ -453,7 +545,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
str_type = strdup( strtok( typeAndVersionAndCounter, ":" ) );
|
||||
str_algorithm = strdup( strtok( NULL, ":" ) );
|
||||
str_counter = strdup( strtok( NULL, "" ) );
|
||||
mpw_free_string( typeAndVersionAndCounter );
|
||||
mpw_free_string( &typeAndVersionAndCounter );
|
||||
}
|
||||
siteLoginName = mpw_get_token( &positionInLine, endOfLine, "\t\n" );
|
||||
siteName = mpw_get_token( &positionInLine, endOfLine, "\t\n" );
|
||||
@@ -497,10 +589,8 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
site->loginName = siteLoginName? strdup( siteLoginName ): NULL;
|
||||
site->uses = (unsigned int)atoi( str_uses );
|
||||
site->lastUsed = siteLastUsed;
|
||||
if (siteContent && strlen( siteContent )) {
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
|
||||
@@ -508,12 +598,19 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (siteContent && strlen( siteContent ))
|
||||
site->content = mpw_siteState( masterKey, site->name, site->counter,
|
||||
MPKeyPurposeAuthentication, NULL, site->type, siteContent, site->algorithm );
|
||||
if (siteLoginName && strlen( siteLoginName ))
|
||||
site->loginContent = mpw_siteState( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeIdentification, NULL, site->loginType, siteLoginName, site->algorithm );
|
||||
}
|
||||
else
|
||||
else {
|
||||
// Redacted
|
||||
if (siteContent && strlen( siteContent ))
|
||||
site->content = strdup( siteContent );
|
||||
if (siteLoginName && strlen( siteLoginName ))
|
||||
site->loginContent = strdup( siteLoginName );
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -524,27 +621,50 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mpw_free_string( str_lastUsed );
|
||||
mpw_free_string( str_uses );
|
||||
mpw_free_string( str_type );
|
||||
mpw_free_string( str_algorithm );
|
||||
mpw_free_string( str_counter );
|
||||
mpw_free_string( siteLoginName );
|
||||
mpw_free_string( siteName );
|
||||
mpw_free_string( siteContent );
|
||||
mpw_free_strings( &str_lastUsed, &str_uses, &str_type, &str_algorithm, &str_counter, NULL );
|
||||
mpw_free_strings( &siteLoginName, &siteName, &siteContent, NULL );
|
||||
}
|
||||
mpw_free_string( fullName );
|
||||
mpw_free_string( keyID );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
mpw_free_strings( &fullName, &keyID, NULL );
|
||||
mpw_free( &masterKey, MPMasterKeySize );
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallSuccess };
|
||||
*error = (MPMarshallError){ .type = MPMarshallSuccess };
|
||||
return user;
|
||||
}
|
||||
|
||||
static MPMarshalledUser *mpw_marshall_read_json(
|
||||
char *in, const char *masterPassword, MPMarshallError *error) {
|
||||
#if MPW_JSON
|
||||
static void mpw_marshall_read_json_info(
|
||||
const char *in, MPMarshallInfo *info) {
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal };
|
||||
// Parse JSON.
|
||||
enum json_tokener_error json_error = json_tokener_success;
|
||||
json_object *json_file = json_tokener_parse_verbose( in, &json_error );
|
||||
if (!json_file || json_error != json_tokener_success)
|
||||
return;
|
||||
|
||||
// Section: "export"
|
||||
int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 );
|
||||
if (fileFormat < 1)
|
||||
return;
|
||||
info->redacted = mpw_get_json_boolean( json_file, "export.redacted", true );
|
||||
info->date = mpw_mktime( mpw_get_json_string( json_file, "export.date", NULL ) );
|
||||
|
||||
// Section: "user"
|
||||
info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent );
|
||||
info->fullName = strdup( mpw_get_json_string( json_file, "user.full_name", NULL ) );
|
||||
info->keyID = strdup( mpw_get_json_string( json_file, "user.key_id", NULL ) );
|
||||
|
||||
json_object_put( json_file );
|
||||
}
|
||||
|
||||
static MPMarshalledUser *mpw_marshall_read_json(
|
||||
const char *in, const char *masterPassword, MPMarshallError *error) {
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal, "Unexpected internal error." };
|
||||
if (!in || !strlen( in )) {
|
||||
error->type = MPMarshallErrorStructure;
|
||||
error->description = mpw_str( "No input data." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Parse JSON.
|
||||
enum json_tokener_error json_error = json_tokener_success;
|
||||
@@ -560,7 +680,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
MPMarshalledUser *user = NULL;
|
||||
|
||||
// Section: "export"
|
||||
unsigned int fileFormat = (unsigned int)mpw_get_json_int( json_file, "export.format", 0 );
|
||||
int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 );
|
||||
if (fileFormat < 1) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported format: %u", fileFormat ) };
|
||||
return NULL;
|
||||
@@ -572,7 +692,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
const char *fullName = mpw_get_json_string( json_file, "user.full_name", NULL );
|
||||
const char *str_lastUsed = mpw_get_json_string( json_file, "user.last_used", NULL );
|
||||
const char *keyID = mpw_get_json_string( json_file, "user.key_id", NULL );
|
||||
int32_t value = mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent );
|
||||
int64_t value = mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent );
|
||||
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid user algorithm version: %u", value ) };
|
||||
return NULL;
|
||||
@@ -614,13 +734,13 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
json_object *json_sites = mpw_get_json_section( json_file, "sites" );
|
||||
json_object_object_foreachC( json_sites, json_site ) {
|
||||
const char *siteName = json_site.key;
|
||||
value = mpw_get_json_int( json_site.val, "algorithm", user->algorithm );
|
||||
value = mpw_get_json_int( json_site.val, "algorithm", (int32_t)user->algorithm );
|
||||
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site algorithm version: %s: %d", siteName, value ) };
|
||||
return NULL;
|
||||
}
|
||||
MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)value;
|
||||
MPResultType siteType = (MPResultType)mpw_get_json_int( json_site.val, "type", user->defaultType );
|
||||
MPResultType siteType = (MPResultType)mpw_get_json_int( json_site.val, "type", (int32_t)user->defaultType );
|
||||
if (!mpw_nameForType( siteType )) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %u", siteName, siteType ) };
|
||||
return NULL;
|
||||
@@ -633,7 +753,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
MPCounterValue siteCounter = (MPCounterValue)value;
|
||||
const char *siteContent = mpw_get_json_string( json_site.val, "password", NULL );
|
||||
const char *siteLoginName = mpw_get_json_string( json_site.val, "login_name", NULL );
|
||||
bool siteLoginGenerated = mpw_get_json_boolean( json_site.val, "login_generated", false );
|
||||
MPResultType siteLoginType = (MPResultType)mpw_get_json_int( json_site.val, "login_type", MPResultTypeTemplateName );
|
||||
unsigned int siteUses = (unsigned int)mpw_get_json_int( json_site.val, "uses", 0 );
|
||||
str_lastUsed = mpw_get_json_string( json_site.val, "last_used", NULL );
|
||||
time_t siteLastUsed = mpw_mktime( str_lastUsed );
|
||||
@@ -651,12 +771,10 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
site->loginName = siteLoginName? strdup( siteLoginName ): NULL;
|
||||
site->loginGenerated = siteLoginGenerated;
|
||||
site->loginType = siteLoginType;
|
||||
site->url = siteURL? strdup( siteURL ): NULL;
|
||||
site->uses = siteUses;
|
||||
site->lastUsed = siteLastUsed;
|
||||
if (siteContent && strlen( siteContent )) {
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
|
||||
@@ -664,33 +782,83 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (siteContent && strlen( siteContent ))
|
||||
site->content = mpw_siteState( masterKey, site->name, site->counter,
|
||||
MPKeyPurposeAuthentication, NULL, site->type, siteContent, site->algorithm );
|
||||
if (siteLoginName && strlen( siteLoginName ))
|
||||
site->loginContent = mpw_siteState( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeIdentification, NULL, site->loginType, siteLoginName, site->algorithm );
|
||||
}
|
||||
else
|
||||
else {
|
||||
// Redacted
|
||||
if (siteContent && strlen( siteContent ))
|
||||
site->content = strdup( siteContent );
|
||||
if (siteLoginName && strlen( siteLoginName ))
|
||||
site->loginContent = strdup( siteLoginName );
|
||||
}
|
||||
|
||||
json_object_iter json_site_question;
|
||||
json_object *json_site_questions = mpw_get_json_section( json_site.val, "questions" );
|
||||
json_object_object_foreachC( json_site_questions, json_site_question )
|
||||
mpw_marshal_question( site, json_site_question.key );
|
||||
json_object_object_foreachC( json_site_questions, json_site_question ) {
|
||||
MPMarshalledQuestion *question = mpw_marshal_question( site, json_site_question.key );
|
||||
const char *answerContent = mpw_get_json_string( json_site_question.val, "answer", NULL );
|
||||
question->type = (MPResultType)mpw_get_json_int( json_site_question.val, "type", MPResultTypeTemplatePhrase );
|
||||
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (answerContent && strlen( answerContent ))
|
||||
question->content = mpw_siteState( masterKey, site->name, MPCounterValueInitial,
|
||||
MPKeyPurposeRecovery, question->keyword, question->type, answerContent, site->algorithm );
|
||||
}
|
||||
else {
|
||||
// Redacted
|
||||
if (answerContent && strlen( answerContent ))
|
||||
question->content = strdup( answerContent );
|
||||
}
|
||||
}
|
||||
}
|
||||
json_object_put( json_file );
|
||||
|
||||
*error = (MPMarshallError){ MPMarshallSuccess };
|
||||
*error = (MPMarshallError){ .type = MPMarshallSuccess };
|
||||
return user;
|
||||
}
|
||||
#endif
|
||||
|
||||
MPMarshallInfo *mpw_marshall_read_info(
|
||||
const char *in) {
|
||||
|
||||
MPMarshallInfo *info = malloc( sizeof( MPMarshallInfo ) );
|
||||
*info = (MPMarshallInfo){ .format = MPMarshallFormatNone };
|
||||
|
||||
if (in && strlen( in )) {
|
||||
if (in[0] == '#') {
|
||||
*info = (MPMarshallInfo){ .format = MPMarshallFormatFlat };
|
||||
mpw_marshall_read_flat_info( in, info );
|
||||
}
|
||||
else if (in[0] == '{') {
|
||||
*info = (MPMarshallInfo){ .format = MPMarshallFormatJSON };
|
||||
#if MPW_JSON
|
||||
mpw_marshall_read_json_info( in, info );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
MPMarshalledUser *mpw_marshall_read(
|
||||
char *in, const MPMarshallFormat inFormat, const char *masterPassword, MPMarshallError *error) {
|
||||
const char *in, const MPMarshallFormat inFormat, const char *masterPassword, MPMarshallError *error) {
|
||||
|
||||
switch (inFormat) {
|
||||
case MPMarshallFormatNone:
|
||||
*error = (MPMarshallError){ .type = MPMarshallSuccess };
|
||||
return false;
|
||||
case MPMarshallFormatFlat:
|
||||
return mpw_marshall_read_flat( in, masterPassword, error );
|
||||
#if MPW_JSON
|
||||
case MPMarshallFormatJSON:
|
||||
return mpw_marshall_read_json( in, masterPassword, error );
|
||||
#endif
|
||||
default:
|
||||
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) };
|
||||
return NULL;
|
||||
@@ -700,6 +868,9 @@ MPMarshalledUser *mpw_marshall_read(
|
||||
const MPMarshallFormat mpw_formatWithName(
|
||||
const char *formatName) {
|
||||
|
||||
if (!formatName || !strlen( formatName ))
|
||||
return MPMarshallFormatNone;
|
||||
|
||||
// Lower-case to standardize it.
|
||||
size_t stdFormatNameSize = strlen( formatName );
|
||||
char stdFormatName[stdFormatNameSize + 1];
|
||||
@@ -707,6 +878,8 @@ const MPMarshallFormat mpw_formatWithName(
|
||||
stdFormatName[c] = (char)tolower( formatName[c] );
|
||||
stdFormatName[stdFormatNameSize] = '\0';
|
||||
|
||||
if (strncmp( mpw_nameForFormat( MPMarshallFormatNone ), stdFormatName, strlen( stdFormatName ) ) == 0)
|
||||
return MPMarshallFormatNone;
|
||||
if (strncmp( mpw_nameForFormat( MPMarshallFormatFlat ), stdFormatName, strlen( stdFormatName ) ) == 0)
|
||||
return MPMarshallFormatFlat;
|
||||
if (strncmp( mpw_nameForFormat( MPMarshallFormatJSON ), stdFormatName, strlen( stdFormatName ) ) == 0)
|
||||
@@ -720,6 +893,8 @@ const char *mpw_nameForFormat(
|
||||
const MPMarshallFormat format) {
|
||||
|
||||
switch (format) {
|
||||
case MPMarshallFormatNone:
|
||||
return "none";
|
||||
case MPMarshallFormatFlat:
|
||||
return "flat";
|
||||
case MPMarshallFormatJSON:
|
||||
@@ -735,6 +910,8 @@ const char *mpw_marshall_format_extension(
|
||||
const MPMarshallFormat format) {
|
||||
|
||||
switch (format) {
|
||||
case MPMarshallFormatNone:
|
||||
return NULL;
|
||||
case MPMarshallFormatFlat:
|
||||
return "mpsites";
|
||||
case MPMarshallFormatJSON:
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
//// Types.
|
||||
|
||||
typedef enum( unsigned int, MPMarshallFormat ) {
|
||||
typedef mpw_enum( unsigned int, MPMarshallFormat ) {
|
||||
/** Generate a key for authentication. */
|
||||
MPMarshallFormatNone,
|
||||
/** Generate a key for authentication. */
|
||||
MPMarshallFormatFlat,
|
||||
/** Generate a name for identification. */
|
||||
@@ -34,7 +36,7 @@ typedef enum( unsigned int, MPMarshallFormat ) {
|
||||
MPMarshallFormatDefault = MPMarshallFormatJSON,
|
||||
};
|
||||
|
||||
typedef enum( unsigned int, MPMarshallErrorType ) {
|
||||
typedef mpw_enum( unsigned int, MPMarshallErrorType ) {
|
||||
/** The marshalling operation completed successfully. */
|
||||
MPMarshallSuccess,
|
||||
/** An error in the structure of the marshall file interrupted marshalling. */
|
||||
@@ -57,6 +59,8 @@ typedef struct MPMarshallError {
|
||||
|
||||
typedef struct MPMarshalledQuestion {
|
||||
const char *keyword;
|
||||
const char *content;
|
||||
MPResultType type;
|
||||
} MPMarshalledQuestion;
|
||||
|
||||
typedef struct MPMarshalledSite {
|
||||
@@ -66,8 +70,8 @@ typedef struct MPMarshalledSite {
|
||||
MPCounterValue counter;
|
||||
MPAlgorithmVersion algorithm;
|
||||
|
||||
const char *loginName;
|
||||
bool loginGenerated;
|
||||
const char *loginContent;
|
||||
MPResultType loginType;
|
||||
|
||||
const char *url;
|
||||
unsigned int uses;
|
||||
@@ -91,24 +95,44 @@ typedef struct MPMarshalledUser {
|
||||
MPMarshalledSite *sites;
|
||||
} MPMarshalledUser;
|
||||
|
||||
typedef struct MPMarshallInfo {
|
||||
MPMarshallFormat format;
|
||||
MPAlgorithmVersion algorithm;
|
||||
const char *fullName;
|
||||
const char *keyID;
|
||||
bool redacted;
|
||||
time_t date;
|
||||
} MPMarshallInfo;
|
||||
|
||||
//// Marshalling.
|
||||
|
||||
/** Write the user and all associated data out to the given output buffer using the given marshalling format. */
|
||||
bool mpw_marshall_write(
|
||||
char **out, const MPMarshallFormat outFormat, const MPMarshalledUser *user, MPMarshallError *error);
|
||||
/** Try to read metadata on the sites in the input buffer. */
|
||||
MPMarshallInfo *mpw_marshall_read_info(
|
||||
const char *in);
|
||||
/** Unmarshall sites in the given input buffer by parsing it using the given marshalling format. */
|
||||
MPMarshalledUser *mpw_marshall_read(
|
||||
char *in, const MPMarshallFormat inFormat, const char *masterPassword, MPMarshallError *error);
|
||||
const char *in, const MPMarshallFormat inFormat, const char *masterPassword, MPMarshallError *error);
|
||||
|
||||
//// Utilities.
|
||||
|
||||
/** Create a new user object ready for marshalling. */
|
||||
MPMarshalledUser *mpw_marshall_user(
|
||||
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
|
||||
/** Create a new site attached to the given user object, ready for marshalling. */
|
||||
MPMarshalledSite *mpw_marshall_site(
|
||||
MPMarshalledUser *user,
|
||||
const char *siteName, const MPResultType resultType, const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion);
|
||||
/** Create a new question attached to the given site object, ready for marshalling. */
|
||||
MPMarshalledQuestion *mpw_marshal_question(
|
||||
MPMarshalledSite *site, const char *keyword);
|
||||
/** Free the given user object and all associated data. */
|
||||
bool mpw_marshal_info_free(
|
||||
MPMarshallInfo **info);
|
||||
bool mpw_marshal_free(
|
||||
MPMarshalledUser *user);
|
||||
MPMarshalledUser **user);
|
||||
|
||||
//// Format.
|
||||
|
||||
@@ -122,6 +146,9 @@ const MPMarshallFormat mpw_formatWithName(
|
||||
*/
|
||||
const char *mpw_nameForFormat(
|
||||
const MPMarshallFormat format);
|
||||
/**
|
||||
* @return The file extension that's recommended for files that use the given marshalling format.
|
||||
*/
|
||||
const char *mpw_marshall_format_extension(
|
||||
const MPMarshallFormat format);
|
||||
|
||||
|
||||
@@ -16,16 +16,9 @@
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef COLOR
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
#endif
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
@@ -48,9 +41,9 @@ const MPResultType mpw_typeWithName(const char *typeName) {
|
||||
if ('n' == typeName[0])
|
||||
return MPResultTypeTemplateName;
|
||||
if ('P' == typeName[0])
|
||||
return MPResultTypeStatePersonal;
|
||||
return MPResultTypeStatefulPersonal;
|
||||
if ('D' == typeName[0])
|
||||
return MPResultTypeStateDevice;
|
||||
return MPResultTypeStatefulDevice;
|
||||
if ('k' == typeName[0])
|
||||
return MPResultTypeDeriveKey;
|
||||
}
|
||||
@@ -82,10 +75,10 @@ const MPResultType mpw_typeWithName(const char *typeName) {
|
||||
return MPResultTypeTemplateName;
|
||||
if (strncmp( mpw_nameForType( MPResultTypeTemplatePhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||
return MPResultTypeTemplatePhrase;
|
||||
if (strncmp( mpw_nameForType( MPResultTypeStatePersonal ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||
return MPResultTypeStatePersonal;
|
||||
if (strncmp( mpw_nameForType( MPResultTypeStateDevice ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||
return MPResultTypeStateDevice;
|
||||
if (strncmp( mpw_nameForType( MPResultTypeStatefulPersonal ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||
return MPResultTypeStatefulPersonal;
|
||||
if (strncmp( mpw_nameForType( MPResultTypeStatefulDevice ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||
return MPResultTypeStatefulDevice;
|
||||
if (strncmp( mpw_nameForType( MPResultTypeDeriveKey ), stdTypeName, strlen( stdTypeName ) ) == 0)
|
||||
return MPResultTypeDeriveKey;
|
||||
|
||||
@@ -112,9 +105,9 @@ const char *mpw_nameForType(MPResultType resultType) {
|
||||
return "name";
|
||||
case MPResultTypeTemplatePhrase:
|
||||
return "phrase";
|
||||
case MPResultTypeStatePersonal:
|
||||
case MPResultTypeStatefulPersonal:
|
||||
return "personal";
|
||||
case MPResultTypeStateDevice:
|
||||
case MPResultTypeStatefulDevice:
|
||||
return "device";
|
||||
case MPResultTypeDeriveKey:
|
||||
return "key";
|
||||
@@ -170,11 +163,11 @@ const char **mpw_templatesForType(MPResultType type, size_t *count) {
|
||||
}
|
||||
}
|
||||
|
||||
const char *mpw_templateForType(MPResultType type, uint8_t seedByte) {
|
||||
const char *mpw_templateForType(MPResultType type, uint8_t templateIndex) {
|
||||
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
char const *template = templates && count? templates[seedByte % count]: NULL;
|
||||
char const *template = templates && count? templates[templateIndex % count]: NULL;
|
||||
free( templates );
|
||||
|
||||
return template;
|
||||
|
||||
@@ -23,11 +23,15 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
//#ifdef NS_ENUM
|
||||
//#define enum(_type, _name) NS_ENUM(_type, _name)
|
||||
//#else
|
||||
#define enum(_type, _name) _type _name; enum
|
||||
//#endif
|
||||
#ifdef NS_ENUM
|
||||
#define mpw_enum(_type, _name) NS_ENUM(_type, _name)
|
||||
#else
|
||||
#define mpw_enum(_type, _name) _type _name; enum
|
||||
#endif
|
||||
|
||||
#ifndef __unused
|
||||
#define __unused __attribute__((unused))
|
||||
#endif
|
||||
|
||||
//// Types.
|
||||
|
||||
@@ -37,7 +41,7 @@ typedef const uint8_t *MPMasterKey;
|
||||
typedef const uint8_t *MPSiteKey;
|
||||
typedef const char *MPKeyID;
|
||||
|
||||
typedef enum( uint8_t, MPKeyPurpose ) {
|
||||
typedef mpw_enum( uint8_t, MPKeyPurpose ) {
|
||||
/** Generate a key for authentication. */
|
||||
MPKeyPurposeAuthentication,
|
||||
/** Generate a name for identification. */
|
||||
@@ -47,17 +51,17 @@ typedef enum( uint8_t, MPKeyPurpose ) {
|
||||
};
|
||||
|
||||
// bit 4 - 9
|
||||
typedef enum( uint16_t, MPResultTypeClass ) {
|
||||
typedef mpw_enum( uint16_t, MPResultTypeClass ) {
|
||||
/** Use the site key to generate a password from a template. */
|
||||
MPResultTypeClassTemplate = 1 << 4,
|
||||
/** Use the site key to encrypt and decrypt a stateful entity. */
|
||||
MPResultTypeClassState = 1 << 5,
|
||||
MPResultTypeClassStateful = 1 << 5,
|
||||
/** Use the site key to derive a site-specific object. */
|
||||
MPResultTypeClassDerive = 1 << 6,
|
||||
};
|
||||
|
||||
// bit 10 - 15
|
||||
typedef enum( uint16_t, MPSiteFeature ) {
|
||||
typedef mpw_enum( uint16_t, MPSiteFeature ) {
|
||||
/** Export the key-protected content data. */
|
||||
MPSiteFeatureExportContent = 1 << 10,
|
||||
/** Never export content. */
|
||||
@@ -67,7 +71,7 @@ typedef enum( uint16_t, MPSiteFeature ) {
|
||||
};
|
||||
|
||||
// bit 0-3 | MPResultTypeClass | MPSiteFeature
|
||||
typedef enum( uint32_t, MPResultType ) {
|
||||
typedef mpw_enum( uint32_t, MPResultType ) {
|
||||
/** pg^VMAUBk5x3p%HP%i4= */
|
||||
MPResultTypeTemplateMaximum = 0x0 | MPResultTypeClassTemplate | 0x0,
|
||||
/** BiroYena8:Kixa */
|
||||
@@ -86,9 +90,9 @@ typedef enum( uint32_t, MPResultType ) {
|
||||
MPResultTypeTemplatePhrase = 0xF | MPResultTypeClassTemplate | 0x0,
|
||||
|
||||
/** Custom saved password. */
|
||||
MPResultTypeStatePersonal = 0x0 | MPResultTypeClassState | MPSiteFeatureExportContent,
|
||||
MPResultTypeStatefulPersonal = 0x0 | MPResultTypeClassStateful | MPSiteFeatureExportContent,
|
||||
/** Custom saved password that should not be exported from the device. */
|
||||
MPResultTypeStateDevice = 0x1 | MPResultTypeClassState | MPSiteFeatureDevicePrivate,
|
||||
MPResultTypeStatefulDevice = 0x1 | MPResultTypeClassStateful | MPSiteFeatureDevicePrivate,
|
||||
|
||||
/** Derive a unique binary key. */
|
||||
MPResultTypeDeriveKey = 0x0 | MPResultTypeClassDerive | MPSiteFeatureAlternative,
|
||||
@@ -96,7 +100,7 @@ typedef enum( uint32_t, MPResultType ) {
|
||||
MPResultTypeDefault = MPResultTypeTemplateLong,
|
||||
};
|
||||
|
||||
typedef enum ( uint32_t, MPCounterValue ) {
|
||||
typedef mpw_enum ( uint32_t, MPCounterValue ) {
|
||||
/** Use a time-based counter value, resulting in a TOTP generator. */
|
||||
MPCounterValueTOTP = 0,
|
||||
/** The initial value for a site's counter. */
|
||||
@@ -142,7 +146,7 @@ const char **mpw_templatesForType(MPResultType type, size_t *count);
|
||||
* @return An internal string that contains the password encoding template of the given type
|
||||
* for a seed that starts with the given byte.
|
||||
*/
|
||||
const char *mpw_templateForType(MPResultType type, uint8_t seedByte);
|
||||
const char *mpw_templateForType(MPResultType type, uint8_t templateIndex);
|
||||
|
||||
/**
|
||||
* @return An internal string that contains all the characters that occur in the given character class.
|
||||
|
||||
@@ -26,34 +26,57 @@
|
||||
#include <term.h>
|
||||
#endif
|
||||
|
||||
#if HAS_CPERCIVA
|
||||
#if MPW_CPERCIVA
|
||||
#include <scrypt/crypto_scrypt.h>
|
||||
#include <scrypt/sha256.h>
|
||||
#elif HAS_SODIUM
|
||||
#elif MPW_SODIUM
|
||||
#include "sodium.h"
|
||||
#ifdef SODIUM_LIBRARY_MINIMAL
|
||||
#include "crypto_stream_aes128ctr.h"
|
||||
#include "crypto_kdf_blake2b.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
#ifdef inf_level
|
||||
int mpw_verbosity = inf_level;
|
||||
#endif
|
||||
|
||||
bool mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) {
|
||||
void mpw_uint16(const uint16_t number, uint8_t buf[2]) {
|
||||
|
||||
buf[0] = (uint8_t)((number >> 8L) & UINT8_MAX);
|
||||
buf[1] = (uint8_t)((number >> 0L) & UINT8_MAX);
|
||||
}
|
||||
|
||||
void mpw_uint32(const uint32_t number, uint8_t buf[4]) {
|
||||
|
||||
buf[0] = (uint8_t)((number >> 24) & UINT8_MAX);
|
||||
buf[1] = (uint8_t)((number >> 16) & UINT8_MAX);
|
||||
buf[2] = (uint8_t)((number >> 8L) & UINT8_MAX);
|
||||
buf[3] = (uint8_t)((number >> 0L) & UINT8_MAX);
|
||||
}
|
||||
|
||||
void mpw_uint64(const uint64_t number, uint8_t buf[8]) {
|
||||
|
||||
buf[0] = (uint8_t)((number >> 56) & UINT8_MAX);
|
||||
buf[1] = (uint8_t)((number >> 48) & UINT8_MAX);
|
||||
buf[2] = (uint8_t)((number >> 40) & UINT8_MAX);
|
||||
buf[3] = (uint8_t)((number >> 32) & UINT8_MAX);
|
||||
buf[4] = (uint8_t)((number >> 24) & UINT8_MAX);
|
||||
buf[5] = (uint8_t)((number >> 16) & UINT8_MAX);
|
||||
buf[6] = (uint8_t)((number >> 8L) & UINT8_MAX);
|
||||
buf[7] = (uint8_t)((number >> 0L) & UINT8_MAX);
|
||||
}
|
||||
|
||||
bool mpw_push_buf(uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize) {
|
||||
|
||||
if (!buffer || !bufferSize || !pushBuffer || !pushSize)
|
||||
return false;
|
||||
if (*bufferSize == ERR)
|
||||
if (*bufferSize == (size_t)ERR)
|
||||
// The buffer was marked as broken, it is missing a previous push. Abort to avoid corrupt content.
|
||||
return false;
|
||||
|
||||
if (!mpw_realloc( buffer, bufferSize, pushSize )) {
|
||||
// realloc failed, we can't push. Mark the buffer as broken.
|
||||
mpw_free( *buffer, *bufferSize );
|
||||
mpw_free( buffer, *bufferSize );
|
||||
*bufferSize = (size_t)ERR;
|
||||
*buffer = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,13 +85,15 @@ bool mpw_push_buf(uint8_t **const buffer, size_t *const bufferSize, const void *
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mpw_push_string(uint8_t **const buffer, size_t *const bufferSize, const char *pushString) {
|
||||
bool mpw_push_string(uint8_t **buffer, size_t *bufferSize, const char *pushString) {
|
||||
|
||||
return pushString && mpw_push_buf( buffer, bufferSize, pushString, strlen( pushString ) );
|
||||
}
|
||||
|
||||
bool mpw_string_push(char **const string, const char *pushString) {
|
||||
bool mpw_string_push(char **string, const char *pushString) {
|
||||
|
||||
if (!string || !pushString)
|
||||
return false;
|
||||
if (!*string)
|
||||
*string = calloc( 1, sizeof( char ) );
|
||||
|
||||
@@ -76,29 +101,29 @@ bool mpw_string_push(char **const string, const char *pushString) {
|
||||
return pushString && mpw_push_buf( (uint8_t **const)string, &stringLength, pushString, strlen( pushString ) + 1 );
|
||||
}
|
||||
|
||||
bool mpw_string_pushf(char **const string, const char *pushFormat, ...) {
|
||||
bool mpw_string_pushf(char **string, const char *pushFormat, ...) {
|
||||
|
||||
va_list args;
|
||||
va_start( args, pushFormat );
|
||||
char *pushString = NULL;
|
||||
bool success = vasprintf( &pushString, pushFormat, args ) >= 0 && mpw_string_push( string, pushString );
|
||||
bool success = mpw_string_push( string, mpw_vstr( pushFormat, args ) );
|
||||
va_end( args );
|
||||
mpw_free_string( pushString );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool mpw_push_int(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) {
|
||||
bool mpw_push_int(uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt) {
|
||||
|
||||
return mpw_push_buf( buffer, bufferSize, &pushInt, sizeof( pushInt ) );
|
||||
uint8_t pushBuf[4 /* 32 / 8 */];
|
||||
mpw_uint32( pushInt, pushBuf );
|
||||
return mpw_push_buf( buffer, bufferSize, &pushBuf, sizeof( pushBuf ) );
|
||||
}
|
||||
|
||||
bool __mpw_realloc(void **buffer, size_t *bufferSize, const size_t deltaSize) {
|
||||
bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize) {
|
||||
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
void *newBuffer = realloc( *buffer, (bufferSize? *bufferSize: 0) + deltaSize );
|
||||
void *newBuffer = realloc( (void *)*buffer, (bufferSize? *bufferSize: 0) + deltaSize );
|
||||
if (!newBuffer)
|
||||
return false;
|
||||
|
||||
@@ -109,19 +134,35 @@ bool __mpw_realloc(void **buffer, size_t *bufferSize, const size_t deltaSize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mpw_free(const void *buffer, const size_t bufferSize) {
|
||||
bool __mpw_free(const void **buffer, const size_t bufferSize) {
|
||||
|
||||
if (!buffer)
|
||||
if (!buffer || !*buffer)
|
||||
return false;
|
||||
|
||||
memset( (void *)buffer, 0, bufferSize );
|
||||
free( (void *)buffer );
|
||||
memset( (void *)*buffer, 0, bufferSize );
|
||||
free( (void *)*buffer );
|
||||
*buffer = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mpw_free_string(const char *string) {
|
||||
bool __mpw_free_string(const char **string) {
|
||||
|
||||
return string && mpw_free( string, strlen( string ) );
|
||||
return *string && __mpw_free( (const void **)string, strlen( *string ) );
|
||||
}
|
||||
|
||||
bool __mpw_free_strings(const char **strings, ...) {
|
||||
|
||||
bool success = true;
|
||||
|
||||
va_list args;
|
||||
va_start( args, strings );
|
||||
success &= mpw_free_string( strings );
|
||||
for (const char **string; (string = va_arg( args, const char ** ));)
|
||||
success &= mpw_free_string( string );
|
||||
va_end( args );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
uint8_t const *mpw_kdf_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||
@@ -134,14 +175,14 @@ uint8_t const *mpw_kdf_scrypt(const size_t keySize, const char *secret, const ui
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
#if HAS_CPERCIVA
|
||||
#if MPW_CPERCIVA
|
||||
if (crypto_scrypt( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) < 0) {
|
||||
mpw_free( key, keySize );
|
||||
mpw_free( &key, keySize );
|
||||
return NULL;
|
||||
}
|
||||
#elif HAS_SODIUM
|
||||
#elif MPW_SODIUM
|
||||
if (crypto_pwhash_scryptsalsa208sha256_ll( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) != 0) {
|
||||
mpw_free( key, keySize );
|
||||
mpw_free( &key, keySize );
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
@@ -163,7 +204,7 @@ uint8_t const *mpw_kdf_blake2b(const size_t subkeySize, const uint8_t *key, cons
|
||||
if (!subkey)
|
||||
return NULL;
|
||||
|
||||
#if HAS_SODIUM
|
||||
#if MPW_SODIUM
|
||||
if (keySize < crypto_generichash_blake2b_KEYBYTES_MIN || keySize > crypto_generichash_blake2b_KEYBYTES_MAX ||
|
||||
subkeySize < crypto_generichash_blake2b_KEYBYTES_MIN || subkeySize > crypto_generichash_blake2b_KEYBYTES_MAX ||
|
||||
contextSize < crypto_generichash_blake2b_BYTES_MIN || contextSize > crypto_generichash_blake2b_BYTES_MAX ||
|
||||
@@ -175,10 +216,8 @@ uint8_t const *mpw_kdf_blake2b(const size_t subkeySize, const uint8_t *key, cons
|
||||
|
||||
uint8_t saltBuf[crypto_generichash_blake2b_SALTBYTES];
|
||||
bzero( saltBuf, sizeof saltBuf );
|
||||
if (id) {
|
||||
uint64_t id_n = htonll( id );
|
||||
memcpy( saltBuf, &id_n, sizeof id_n );
|
||||
}
|
||||
if (id)
|
||||
mpw_uint64( id, saltBuf );
|
||||
|
||||
uint8_t personalBuf[crypto_generichash_blake2b_PERSONALBYTES];
|
||||
bzero( personalBuf, sizeof saltBuf );
|
||||
@@ -186,7 +225,7 @@ uint8_t const *mpw_kdf_blake2b(const size_t subkeySize, const uint8_t *key, cons
|
||||
memcpy( personalBuf, personal, strlen( personal ) );
|
||||
|
||||
if (crypto_generichash_blake2b_salt_personal( subkey, subkeySize, context, contextSize, key, keySize, saltBuf, personalBuf ) != 0) {
|
||||
mpw_free( subkey, subkeySize );
|
||||
mpw_free( &subkey, subkeySize );
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
@@ -201,13 +240,13 @@ uint8_t const *mpw_hash_hmac_sha256(const uint8_t *key, const size_t keySize, co
|
||||
if (!key || !keySize || !message || !messageSize)
|
||||
return NULL;
|
||||
|
||||
#if HAS_CPERCIVA
|
||||
#if MPW_CPERCIVA
|
||||
uint8_t *const mac = malloc( 32 );
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
HMAC_SHA256_Buf( key, keySize, message, messageSize, mac );
|
||||
#elif HAS_SODIUM
|
||||
#elif MPW_SODIUM
|
||||
uint8_t *const mac = malloc( crypto_auth_hmacsha256_BYTES );
|
||||
if (!mac)
|
||||
return NULL;
|
||||
@@ -216,7 +255,7 @@ uint8_t const *mpw_hash_hmac_sha256(const uint8_t *key, const size_t keySize, co
|
||||
if (crypto_auth_hmacsha256_init( &state, key, keySize ) != 0 ||
|
||||
crypto_auth_hmacsha256_update( &state, message, messageSize ) != 0 ||
|
||||
crypto_auth_hmacsha256_final( &state, mac ) != 0) {
|
||||
mpw_free( mac, crypto_auth_hmacsha256_BYTES );
|
||||
mpw_free( &mac, crypto_auth_hmacsha256_BYTES );
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
@@ -228,7 +267,7 @@ uint8_t const *mpw_hash_hmac_sha256(const uint8_t *key, const size_t keySize, co
|
||||
|
||||
static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t keySize, const uint8_t *buf, const size_t bufSize) {
|
||||
|
||||
#if HAS_SODIUM
|
||||
#if MPW_SODIUM
|
||||
if (!key || keySize < crypto_stream_KEYBYTES)
|
||||
return NULL;
|
||||
|
||||
@@ -242,7 +281,7 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key
|
||||
if (encrypt) {
|
||||
uint8_t *const cipherBuf = malloc( bufSize );
|
||||
if (crypto_stream_aes128ctr_xor( cipherBuf, buf, bufSize, nonce, key ) != 0) {
|
||||
mpw_free( cipherBuf, bufSize );
|
||||
mpw_free( &cipherBuf, bufSize );
|
||||
return NULL;
|
||||
}
|
||||
return cipherBuf;
|
||||
@@ -250,7 +289,7 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key
|
||||
else {
|
||||
uint8_t *const plainBuf = malloc( bufSize );
|
||||
if (crypto_stream_aes128ctr( plainBuf, bufSize, nonce, key ) != 0) {
|
||||
mpw_free( plainBuf, bufSize );
|
||||
mpw_free( &plainBuf, bufSize );
|
||||
return NULL;
|
||||
}
|
||||
for (size_t c = 0; c < bufSize; ++c)
|
||||
@@ -274,15 +313,44 @@ uint8_t const *mpw_aes_decrypt(const uint8_t *key, const size_t keySize, const u
|
||||
return mpw_aes( false, key, keySize, cipherBuf, bufSize );
|
||||
}
|
||||
|
||||
#if UNUSED
|
||||
const char *mpw_hotp(const uint8_t *key, size_t keySize, uint64_t movingFactor, uint8_t digits, uint8_t truncationOffset) {
|
||||
|
||||
// Hash the moving factor with the key.
|
||||
uint8_t counter[8];
|
||||
mpw_uint64( movingFactor, counter );
|
||||
uint8_t hash[20];
|
||||
hmac_sha1( key, keySize, counter, sizeof( counter ), hash );
|
||||
|
||||
// Determine the offset to select OTP bytes from.
|
||||
int offset;
|
||||
if ((truncationOffset >= 0) && (truncationOffset < (sizeof( hash ) - 4)))
|
||||
offset = truncationOffset;
|
||||
else
|
||||
offset = hash[sizeof( hash ) - 1] & 0xf;
|
||||
|
||||
// Select four bytes from the truncation offset.
|
||||
uint32_t otp = 0U
|
||||
| ((hash[offset + 0] & 0x7f) << 24)
|
||||
| ((hash[offset + 1] & 0xff) << 16)
|
||||
| ((hash[offset + 2] & 0xff) << 8)
|
||||
| ((hash[offset + 3] & 0xff) << 0);
|
||||
|
||||
// Render the OTP as `digits` decimal digits.
|
||||
otp %= (int)pow(10, digits);
|
||||
return strdup( mpw_str( "%0*d", digits, otp ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
MPKeyID mpw_id_buf(const void *buf, size_t length) {
|
||||
|
||||
if (!buf)
|
||||
return "<unset>";
|
||||
|
||||
#if HAS_CPERCIVA
|
||||
#if MPW_CPERCIVA
|
||||
uint8_t hash[32];
|
||||
SHA256_Buf( buf, length, hash );
|
||||
#elif HAS_SODIUM
|
||||
#elif MPW_SODIUM
|
||||
uint8_t hash[crypto_hash_sha256_BYTES];
|
||||
crypto_hash_sha256( hash, buf, length );
|
||||
#else
|
||||
@@ -305,24 +373,50 @@ bool mpw_id_buf_equals(const char *id1, const char *id2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *str_str;
|
||||
|
||||
const char *mpw_str(const char *format, ...) {
|
||||
|
||||
va_list args;
|
||||
va_start( args, format );
|
||||
vasprintf( &str_str, format, args );
|
||||
const char *str_str = mpw_vstr( format, args );
|
||||
va_end( args );
|
||||
|
||||
return str_str;
|
||||
}
|
||||
|
||||
static char **mpw_hex_buf;
|
||||
static unsigned int mpw_hex_buf_i;
|
||||
const char *mpw_vstr(const char *format, va_list args) {
|
||||
|
||||
// TODO: We should find a way to get rid of this shared storage medium.
|
||||
// TODO: Not thread-safe
|
||||
static char *str_str;
|
||||
static size_t str_str_max;
|
||||
if (!str_str && !(str_str = calloc( str_str_max = 1, sizeof( char ) )))
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
va_list args_attempt;
|
||||
va_copy( args_attempt, args );
|
||||
size_t len = (size_t)vsnprintf( str_str, str_str_max, format, args_attempt );
|
||||
va_end( args_attempt );
|
||||
|
||||
if ((int)len < 0)
|
||||
return NULL;
|
||||
if (len < str_str_max)
|
||||
break;
|
||||
|
||||
if (!mpw_realloc( &str_str, &str_str_max, len - str_str_max + 1 ))
|
||||
return NULL;
|
||||
} while (true);
|
||||
|
||||
return str_str;
|
||||
}
|
||||
|
||||
const char *mpw_hex(const void *buf, size_t length) {
|
||||
|
||||
// FIXME: Not thread-safe
|
||||
// TODO: We should find a way to get rid of this shared storage medium.
|
||||
// TODO: Not thread-safe
|
||||
static char **mpw_hex_buf;
|
||||
static unsigned int mpw_hex_buf_i;
|
||||
|
||||
if (!mpw_hex_buf)
|
||||
mpw_hex_buf = calloc( 10, sizeof( char * ) );
|
||||
mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10;
|
||||
@@ -336,34 +430,60 @@ const char *mpw_hex(const void *buf, size_t length) {
|
||||
|
||||
const char *mpw_hex_l(uint32_t number) {
|
||||
|
||||
return mpw_hex( &number, sizeof( number ) );
|
||||
uint8_t buf[4 /* 32 / 8 */];
|
||||
buf[0] = (uint8_t)((number >> 24) & UINT8_MAX);
|
||||
buf[1] = (uint8_t)((number >> 16) & UINT8_MAX);
|
||||
buf[2] = (uint8_t)((number >> 8L) & UINT8_MAX);
|
||||
buf[3] = (uint8_t)((number >> 0L) & UINT8_MAX);
|
||||
return mpw_hex( &buf, sizeof( buf ) );
|
||||
}
|
||||
|
||||
#ifdef COLOR
|
||||
static int putvari;
|
||||
static char *putvarc = NULL;
|
||||
static int termsetup;
|
||||
static int initputvar() {
|
||||
#if MPW_COLOR
|
||||
static char *str_tputs;
|
||||
static int str_tputs_cursor;
|
||||
static const int str_tputs_max = 256;
|
||||
|
||||
static bool mpw_setupterm() {
|
||||
|
||||
if (!isatty( STDERR_FILENO ))
|
||||
return 0;
|
||||
if (putvarc)
|
||||
free( putvarc );
|
||||
return false;
|
||||
|
||||
static bool termsetup;
|
||||
if (!termsetup) {
|
||||
int status;
|
||||
if (! (termsetup = (setupterm( NULL, STDERR_FILENO, &status ) == 0 && status == 1))) {
|
||||
wrn( "Terminal doesn't support color (setupterm errno %d).\n", status );
|
||||
return 0;
|
||||
int errret;
|
||||
if (!(termsetup = (setupterm( NULL, STDERR_FILENO, &errret ) == OK))) {
|
||||
wrn( "Terminal doesn't support color (setupterm errret %d).\n", errret );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
putvarc=(char *)calloc(256, sizeof(char));
|
||||
putvari=0;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
static int putvar(int c) {
|
||||
putvarc[putvari++]=c;
|
||||
return 0;
|
||||
|
||||
static int mpw_tputc(int c) {
|
||||
|
||||
if (++str_tputs_cursor < str_tputs_max) {
|
||||
str_tputs[str_tputs_cursor] = (char)c;
|
||||
return OK;
|
||||
}
|
||||
|
||||
return ERR;
|
||||
}
|
||||
|
||||
static char *mpw_tputs(const char *str, int affcnt) {
|
||||
|
||||
if (str_tputs)
|
||||
mpw_free( &str_tputs, str_tputs_max );
|
||||
str_tputs = calloc( str_tputs_max, sizeof( char ) );
|
||||
str_tputs_cursor = -1;
|
||||
|
||||
char *result = tputs( str, affcnt, mpw_tputc ) == ERR? NULL: strndup( str_tputs, str_tputs_max );
|
||||
if (str_tputs)
|
||||
mpw_free( &str_tputs, str_tputs_max );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||
@@ -377,23 +497,20 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌"
|
||||
};
|
||||
|
||||
const uint8_t *identiconSeed = mpw_hash_hmac_sha256( (const uint8_t *)masterPassword, strlen( masterPassword ),
|
||||
(const uint8_t *)fullName,
|
||||
strlen( fullName ) );
|
||||
const uint8_t *identiconSeed = mpw_hash_hmac_sha256(
|
||||
(const uint8_t *)masterPassword, strlen( masterPassword ),
|
||||
(const uint8_t *)fullName, strlen( fullName ) );
|
||||
if (!identiconSeed)
|
||||
return NULL;
|
||||
|
||||
char *colorString, *resetString;
|
||||
#ifdef COLOR
|
||||
if (initputvar()) {
|
||||
#ifdef MPW_COLOR
|
||||
if (mpw_setupterm()) {
|
||||
uint8_t colorIdentifier = (uint8_t)(identiconSeed[4] % 7 + 1);
|
||||
tputs(tparm(tgetstr("AF", NULL), colorIdentifier), 1, putvar);
|
||||
colorString = calloc(strlen(putvarc) + 1, sizeof(char));
|
||||
strcpy(colorString, putvarc);
|
||||
tputs(tgetstr("me", NULL), 1, putvar);
|
||||
resetString = calloc(strlen(putvarc) + 1, sizeof(char));
|
||||
strcpy(resetString, putvarc);
|
||||
} else
|
||||
colorString = mpw_tputs( tparm( tgetstr( "AF", NULL ), colorIdentifier ), 1 );
|
||||
resetString = mpw_tputs( tgetstr( "me", NULL ), 1 );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
colorString = calloc( 1, sizeof( char ) );
|
||||
@@ -409,9 +526,8 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||
accessory[identiconSeed[3] % (sizeof( accessory ) / sizeof( accessory[0] ))],
|
||||
resetString );
|
||||
|
||||
mpw_free( identiconSeed, 32 );
|
||||
free( colorString );
|
||||
free( resetString );
|
||||
mpw_free( &identiconSeed, 32 );
|
||||
mpw_free_strings( &colorString, &resetString, NULL );
|
||||
return identicon;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,42 +31,42 @@ extern int mpw_verbosity;
|
||||
#define trc_level 3
|
||||
/** Logging internal state. */
|
||||
#define trc(...) ({ \
|
||||
if (mpw_verbosity >= 3) \
|
||||
if (mpw_verbosity >= trc_level) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef dbg
|
||||
#define dbg_level 2
|
||||
/** Logging state and events interesting when investigating issues. */
|
||||
#define dbg(...) ({ \
|
||||
if (mpw_verbosity >= 2) \
|
||||
if (mpw_verbosity >= dbg_level) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef inf
|
||||
#define inf_level 1
|
||||
/** User messages. */
|
||||
#define inf(...) ({ \
|
||||
if (mpw_verbosity >= 1) \
|
||||
if (mpw_verbosity >= inf_level) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef wrn
|
||||
#define wrn_level 0
|
||||
/** Recoverable issues and user suggestions. */
|
||||
#define wrn(...) ({ \
|
||||
if (mpw_verbosity >= 0) \
|
||||
if (mpw_verbosity >= wrn_level) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef err
|
||||
#define err_level -1
|
||||
/** Unrecoverable issues. */
|
||||
#define err(...) ({ \
|
||||
if (mpw_verbosity >= -1) \
|
||||
if (mpw_verbosity >= err_level) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
#ifndef ftl
|
||||
#define ftl_level -2
|
||||
/** Issues that lead to abortion. */
|
||||
#define ftl(...) ({ \
|
||||
if (mpw_verbosity >= -2) \
|
||||
if (mpw_verbosity >= ftl_level) \
|
||||
fprintf( stderr, __VA_ARGS__ ); })
|
||||
#endif
|
||||
|
||||
@@ -85,6 +85,9 @@ extern int mpw_verbosity;
|
||||
#ifndef ERR
|
||||
#define ERR -1
|
||||
#endif
|
||||
#ifndef OK
|
||||
#define OK 0
|
||||
#endif
|
||||
#ifndef stringify
|
||||
#define stringify(s) #s
|
||||
#endif
|
||||
@@ -94,6 +97,11 @@ extern int mpw_verbosity;
|
||||
|
||||
//// Buffers and memory.
|
||||
|
||||
/** Write a number to a byte buffer using mpw's endianness (big/network endian). */
|
||||
void mpw_uint16(const uint16_t number, uint8_t buf[2]);
|
||||
void mpw_uint32(const uint32_t number, uint8_t buf[4]);
|
||||
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. */
|
||||
#define mpw_alloc_array(_count, _type, ...) ({ \
|
||||
_type stackElements[] = { __VA_ARGS__ }; \
|
||||
@@ -106,18 +114,18 @@ extern int mpw_verbosity;
|
||||
|
||||
/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */
|
||||
bool mpw_push_buf(
|
||||
uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize);
|
||||
uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize);
|
||||
/** Push a string onto a buffer. reallocs the given buffer and appends the given string. */
|
||||
bool mpw_push_string(
|
||||
uint8_t **buffer, size_t *const bufferSize, const char *pushString);
|
||||
uint8_t **buffer, size_t *bufferSize, const char *pushString);
|
||||
/** Push a string onto another string. reallocs the target string and appends the source string. */
|
||||
bool mpw_string_push(
|
||||
char **const string, const char *pushString);
|
||||
char **string, const char *pushString);
|
||||
bool mpw_string_pushf(
|
||||
char **const string, const char *pushFormat, ...);
|
||||
char **string, const char *pushFormat, ...);
|
||||
/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */
|
||||
bool mpw_push_int(
|
||||
uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt);
|
||||
uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt);
|
||||
/** Reallocate the given buffer from the given size by adding the delta size.
|
||||
* On success, the buffer size pointer will be updated to the buffer's new size
|
||||
* and the buffer pointer may be updated to a new memory address.
|
||||
@@ -128,14 +136,23 @@ bool mpw_push_int(
|
||||
* @return true if successful, false if reallocation failed.
|
||||
*/
|
||||
#define mpw_realloc(buffer, bufferSize, deltaSize) \
|
||||
__mpw_realloc( (void **)buffer, bufferSize, deltaSize )
|
||||
bool __mpw_realloc(void **buffer, size_t *bufferSize, const size_t deltaSize);
|
||||
/** Free a buffer after zero'ing its contents. */
|
||||
bool mpw_free(
|
||||
const void *buffer, const size_t bufferSize);
|
||||
/** Free a string after zero'ing its contents. */
|
||||
bool mpw_free_string(
|
||||
const char *string);
|
||||
({ typeof(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_realloc( (const void **)_b, bufferSize, deltaSize ); })
|
||||
bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize);
|
||||
/** Free a buffer after zero'ing its contents, then set the reference to NULL. */
|
||||
#define mpw_free(buffer, bufferSize) \
|
||||
({ typeof(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_free( (const void **)_b, bufferSize ); })
|
||||
bool __mpw_free(
|
||||
const void **buffer, const size_t bufferSize);
|
||||
/** Free a string after zero'ing its contents, then set the reference to NULL. */
|
||||
#define mpw_free_string(string) \
|
||||
({ typeof(string) _s = string; const char *__s = *_s; (void)__s; __mpw_free_string( (const char **)_s ); })
|
||||
bool __mpw_free_string(
|
||||
const char **string);
|
||||
/** Free strings after zero'ing their contents, then set the references to NULL. Terminate the va_list with NULL. */
|
||||
#define mpw_free_strings(strings, ...) \
|
||||
({ typeof(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (const char **)_s, __VA_ARGS__ ); })
|
||||
bool __mpw_free_strings(
|
||||
const char **strings, ...);
|
||||
|
||||
//// Cryptographic functions.
|
||||
|
||||
@@ -161,12 +178,19 @@ uint8_t const *mpw_aes_encrypt(
|
||||
* @return A new bufSize allocated buffer containing the plainBuf. */
|
||||
uint8_t const *mpw_aes_decrypt(
|
||||
const uint8_t *key, const size_t keySize, const uint8_t *cipherBuf, const size_t bufSize);
|
||||
/** Calculate an OTP using RFC-4226.
|
||||
* @return A newly allocated string containing exactly `digits` decimal OTP digits. */
|
||||
#if UNUSED
|
||||
const char *mpw_hotp(
|
||||
const uint8_t *key, size_t keySize, uint64_t movingFactor, uint8_t digits, uint8_t truncationOffset);
|
||||
#endif
|
||||
|
||||
//// Visualizers.
|
||||
|
||||
/** Compose a formatted string.
|
||||
* @return A C-string in a reused buffer, do not free or store it. */
|
||||
const char *mpw_str(const char *format, ...);
|
||||
const char *mpw_vstr(const char *format, va_list args);
|
||||
/** Encode a buffer as a string of hexadecimal characters.
|
||||
* @return A C-string in a reused buffer, do not free or store it. */
|
||||
const char *mpw_hex(const void *buf, size_t length);
|
||||
|
||||
2
platform-darwin/External/Pearl
vendored
2
platform-darwin/External/Pearl
vendored
Submodule platform-darwin/External/Pearl updated: f0a66e94e8...f513a4a63c
2
platform-darwin/External/libjson-c
vendored
2
platform-darwin/External/libjson-c
vendored
Submodule platform-darwin/External/libjson-c updated: fcad0ec015...3e5ad38a83
@@ -125,7 +125,6 @@
|
||||
DA25C5FF197DBF200046CDCF /* icon_thumbs-up@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD384B1711E29700CF925C /* icon_thumbs-up@2x.png */; };
|
||||
DA25C600197DBF260046CDCF /* icon_trash.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38501711E29700CF925C /* icon_trash.png */; };
|
||||
DA25C601197DBF260046CDCF /* icon_trash@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38511711E29700CF925C /* icon_trash@2x.png */; };
|
||||
DA25C6B41980D3C50046CDCF /* openssl in Headers */ = {isa = PBXBuildFile; fileRef = DA25C6B31980D3C10046CDCF /* openssl */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA29992F19C86F5700AF7DF1 /* thumb_generated_login@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA29992D19C86F5700AF7DF1 /* thumb_generated_login@2x.png */; };
|
||||
DA29993019C86F5700AF7DF1 /* thumb_generated_login.png in Resources */ = {isa = PBXBuildFile; fileRef = DA29992E19C86F5700AF7DF1 /* thumb_generated_login.png */; };
|
||||
DA29993219C9132F00AF7DF1 /* thumb_generated_login@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA29993119C9132F00AF7DF1 /* thumb_generated_login@3x.png */; };
|
||||
@@ -176,6 +175,7 @@
|
||||
DA45224A190628A1008F650A /* icon_wrench@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD386B1711E29700CF925C /* icon_wrench@2x.png */; };
|
||||
DA45224B190628B2008F650A /* icon_gear.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37821711E29500CF925C /* icon_gear.png */; };
|
||||
DA45224C190628B2008F650A /* icon_gear@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37831711E29500CF925C /* icon_gear@2x.png */; };
|
||||
DA45711D1F572F1E00D54152 /* PearlCryptUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DA45711B1F572F1E00D54152 /* PearlCryptUtils.m */; };
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; };
|
||||
DA4DA1DA1564471F00F6F596 /* libuicolor-utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6325D1486805C0075AEA5 /* libuicolor-utilities.a */; };
|
||||
DA5A09DF171A70E4005284AB /* play.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09DD171A70E4005284AB /* play.png */; };
|
||||
@@ -251,6 +251,9 @@
|
||||
DAA1765419D8B82B0044227B /* choose_type.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763E19D8B82B0044227B /* choose_type.png */; };
|
||||
DAA449D21EEC4B5800E7BDD5 /* mpw-marshall.c in Sources */ = {isa = PBXBuildFile; fileRef = DAA449D01EEC4B5800E7BDD5 /* mpw-marshall.c */; };
|
||||
DAADBFE01A68763B00F7A756 /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D3969393A3A46BD27D7078 /* mpw-algorithm.c */; };
|
||||
DAB7AE5D1F3D752900C856B1 /* libjson-c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAB7AE5C1F3D752900C856B1 /* libjson-c.a */; };
|
||||
DAB7AE771F3D755B00C856B1 /* libjson-c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAB7AE761F3D755B00C856B1 /* libjson-c.a */; };
|
||||
DAB7AE991F3DDEE000C856B1 /* mpw-marshall-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DAB7AE981F3DDEE000C856B1 /* mpw-marshall-util.c */; };
|
||||
DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DABB981515100B4000B05417 /* SystemConfiguration.framework */; };
|
||||
DABD39371711E29700CF925C /* avatar-0.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD366C1711E29400CF925C /* avatar-0.png */; };
|
||||
DABD39381711E29700CF925C /* avatar-0@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD366D1711E29400CF925C /* avatar-0@2x.png */; };
|
||||
@@ -403,12 +406,8 @@
|
||||
DAFE4A2F15039824003ABA7C /* PearlStringUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45F415039823003ABA7C /* PearlStringUtils.h */; };
|
||||
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45F515039823003ABA7C /* PearlStringUtils.m */; };
|
||||
DAFE4A3315039824003ABA7C /* Pearl-Crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */; };
|
||||
DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */; };
|
||||
DAFE4A3515039824003ABA7C /* PearlCryptUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */; };
|
||||
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460015039823003ABA7C /* PearlKeyChain.h */; };
|
||||
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460115039823003ABA7C /* PearlKeyChain.m */; };
|
||||
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460215039823003ABA7C /* PearlRSAKey.h */; };
|
||||
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460315039823003ABA7C /* PearlRSAKey.m */; };
|
||||
DAFE4A3C15039824003ABA7C /* Pearl-UIKit-Dependencies.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */; };
|
||||
DAFE4A3D15039824003ABA7C /* Pearl-UIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460915039823003ABA7C /* Pearl-UIKit.h */; };
|
||||
DAFE4A3E15039824003ABA7C /* PearlAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460A15039823003ABA7C /* PearlAlert.h */; };
|
||||
@@ -419,10 +418,6 @@
|
||||
DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460F15039823003ABA7C /* PearlBoxView.m */; };
|
||||
DAFE4A4415039824003ABA7C /* PearlGradientView.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461015039823003ABA7C /* PearlGradientView.h */; };
|
||||
DAFE4A4515039824003ABA7C /* PearlGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461115039823003ABA7C /* PearlGradientView.m */; };
|
||||
DAFE4A4615039824003ABA7C /* PearlLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461215039823003ABA7C /* PearlLayout.h */; };
|
||||
DAFE4A4715039824003ABA7C /* PearlLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461315039823003ABA7C /* PearlLayout.m */; };
|
||||
DAFE4A4815039824003ABA7C /* PearlLayoutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461415039823003ABA7C /* PearlLayoutView.h */; };
|
||||
DAFE4A4915039824003ABA7C /* PearlLayoutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461515039823003ABA7C /* PearlLayoutView.m */; };
|
||||
DAFE4A4A15039824003ABA7C /* PearlMessageView.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461615039823003ABA7C /* PearlMessageView.h */; };
|
||||
DAFE4A4B15039824003ABA7C /* PearlMessageView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE461715039823003ABA7C /* PearlMessageView.m */; };
|
||||
DAFE4A4C15039824003ABA7C /* PearlRootViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE461815039823003ABA7C /* PearlRootViewController.h */; };
|
||||
@@ -452,6 +447,23 @@
|
||||
DAFE4A63150399FF003ABA94 /* NSDateFormatter+RFC3339.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA93 /* NSDateFormatter+RFC3339.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
DAB7AE4D1F3D618700C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DAB7AE471F3D468300C856B1;
|
||||
remoteInfo = "libsodium-ios";
|
||||
};
|
||||
DAB7AE4F1F3D618700C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DAB7AE3D1F3D464A00C856B1;
|
||||
remoteInfo = "libjson-c";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
DA32D01E19D111C6004F3F0E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
@@ -742,7 +754,6 @@
|
||||
DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+PearlReloadItems.h"; sourceTree = "<group>"; };
|
||||
DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionReusableView+PearlDequeue.m"; sourceTree = "<group>"; };
|
||||
DA250A16195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionReusableView+PearlDequeue.h"; sourceTree = "<group>"; };
|
||||
DA25C6B31980D3C10046CDCF /* openssl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = openssl; sourceTree = "<group>"; };
|
||||
DA29992D19C86F5700AF7DF1 /* thumb_generated_login@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_generated_login@2x.png"; sourceTree = "<group>"; };
|
||||
DA29992E19C86F5700AF7DF1 /* thumb_generated_login.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_generated_login.png; sourceTree = "<group>"; };
|
||||
DA29993119C9132F00AF7DF1 /* thumb_generated_login@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_generated_login@3x.png"; sourceTree = "<group>"; };
|
||||
@@ -782,6 +793,8 @@
|
||||
DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = "<group>"; };
|
||||
DA3B844D190FC5DF00246EEA /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = ../../../External/iOS/Crashlytics.framework; sourceTree = "<group>"; };
|
||||
DA3BCFCA19BD09D5006B2681 /* SourceCodePro-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-Regular.otf"; sourceTree = "<group>"; };
|
||||
DA45711B1F572F1E00D54152 /* PearlCryptUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlCryptUtils.m; sourceTree = "<group>"; };
|
||||
DA45711C1F572F1E00D54152 /* PearlCryptUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlCryptUtils.h; sourceTree = "<group>"; };
|
||||
DA5A09DD171A70E4005284AB /* play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = play.png; sourceTree = "<group>"; };
|
||||
DA5A09DE171A70E4005284AB /* play@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "play@2x.png"; sourceTree = "<group>"; };
|
||||
DA5A09E8171BB0F7005284AB /* unlocked.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unlocked.png; sourceTree = "<group>"; };
|
||||
@@ -803,7 +816,6 @@
|
||||
DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Bold.otf"; sourceTree = "<group>"; };
|
||||
DA70EC7F1811B13C00F65DB2 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||
DA771FE41E6E1595004D7EDE /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; };
|
||||
DA7F2C5E1C48B70D00404A26 /* libopensslcrypto-ios-sim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libopensslcrypto-ios-sim.a"; sourceTree = "<group>"; };
|
||||
DA854C8118D4CFBF00106317 /* avatar-add@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add@2x.png"; sourceTree = "<group>"; };
|
||||
DA854C8218D4CFBF00106317 /* avatar-add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add.png"; sourceTree = "<group>"; };
|
||||
DA92614C1BE1A57500369DE5 /* MPAppDelegate_InApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_InApp.h; sourceTree = "<group>"; };
|
||||
@@ -818,16 +830,16 @@
|
||||
DAA1411D1922FF020032B392 /* PearlTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlTween.h; sourceTree = "<group>"; };
|
||||
DAA1411F1922FF020032B392 /* map-macro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "map-macro.h"; sourceTree = "<group>"; };
|
||||
DAA1757D19D86BE70044227B /* libAttributedMarkdown.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAttributedMarkdown.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAA175B119D86C620044227B /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
DAA175B119D86C620044227B /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
DAA175B619D86C620044227B /* markdown_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = markdown_lib.h; sourceTree = "<group>"; };
|
||||
DAA175B719D86C620044227B /* markdown_lib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = markdown_lib.m; sourceTree = "<group>"; };
|
||||
DAA175B819D86C620044227B /* markdown_output.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = markdown_output.m; sourceTree = "<group>"; };
|
||||
DAA175B919D86C620044227B /* markdown_parser.leg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = markdown_parser.leg; sourceTree = "<group>"; };
|
||||
DAA175B919D86C620044227B /* markdown_parser.leg */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = markdown_parser.leg; sourceTree = "<group>"; };
|
||||
DAA175BA19D86C620044227B /* markdown_parser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = markdown_parser.m; sourceTree = "<group>"; };
|
||||
DAA175BB19D86C620044227B /* markdown_peg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = markdown_peg.h; sourceTree = "<group>"; };
|
||||
DAA175EB19D86C620044227B /* parsing_functions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = parsing_functions.m; sourceTree = "<group>"; };
|
||||
DAA175EC19D86C620044227B /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = "<group>"; };
|
||||
DAA175ED19D86C620044227B /* README.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.markdown; sourceTree = "<group>"; };
|
||||
DAA175ED19D86C620044227B /* README.markdown */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = net.daringfireball.markdown; path = README.markdown; sourceTree = "<group>"; };
|
||||
DAA175EE19D86C620044227B /* README_PEG-MARKDWON.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "README_PEG-MARKDWON.markdown"; sourceTree = "<group>"; };
|
||||
DAA175EF19D86C620044227B /* utility_functions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = utility_functions.m; sourceTree = "<group>"; };
|
||||
DAA1761C19D86E800044227B /* attributed-markdown.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "attributed-markdown.pch"; sourceTree = "<group>"; };
|
||||
@@ -862,6 +874,30 @@
|
||||
DAA449D01EEC4B5800E7BDD5 /* mpw-marshall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-marshall.c"; sourceTree = "<group>"; };
|
||||
DAA449D11EEC4B5800E7BDD5 /* mpw-marshall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-marshall.h"; sourceTree = "<group>"; };
|
||||
DAAC35DD156BD77D00C5FD93 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
|
||||
DAB7AE5C1F3D752900C856B1 /* libjson-c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libjson-c.a"; path = "External/libjson-c/libjson-c-ios/lib/libjson-c.a"; sourceTree = "<group>"; };
|
||||
DAB7AE611F3D755B00C856B1 /* arraylist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arraylist.h; sourceTree = "<group>"; };
|
||||
DAB7AE621F3D755B00C856B1 /* bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bits.h; sourceTree = "<group>"; };
|
||||
DAB7AE631F3D755B00C856B1 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
|
||||
DAB7AE641F3D755B00C856B1 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = "<group>"; };
|
||||
DAB7AE651F3D755B00C856B1 /* json_c_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_c_version.h; sourceTree = "<group>"; };
|
||||
DAB7AE661F3D755B00C856B1 /* json_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_config.h; sourceTree = "<group>"; };
|
||||
DAB7AE671F3D755B00C856B1 /* json_inttypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_inttypes.h; sourceTree = "<group>"; };
|
||||
DAB7AE681F3D755B00C856B1 /* json_object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_object.h; sourceTree = "<group>"; };
|
||||
DAB7AE691F3D755B00C856B1 /* json_object_iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_object_iterator.h; sourceTree = "<group>"; };
|
||||
DAB7AE6A1F3D755B00C856B1 /* json_object_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_object_private.h; sourceTree = "<group>"; };
|
||||
DAB7AE6B1F3D755B00C856B1 /* json_pointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_pointer.h; sourceTree = "<group>"; };
|
||||
DAB7AE6C1F3D755B00C856B1 /* json_tokener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_tokener.h; sourceTree = "<group>"; };
|
||||
DAB7AE6D1F3D755B00C856B1 /* json_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_util.h; sourceTree = "<group>"; };
|
||||
DAB7AE6E1F3D755B00C856B1 /* json_visit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_visit.h; sourceTree = "<group>"; };
|
||||
DAB7AE6F1F3D755B00C856B1 /* linkhash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linkhash.h; sourceTree = "<group>"; };
|
||||
DAB7AE701F3D755B00C856B1 /* math_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = math_compat.h; sourceTree = "<group>"; };
|
||||
DAB7AE711F3D755B00C856B1 /* printbuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printbuf.h; sourceTree = "<group>"; };
|
||||
DAB7AE721F3D755B00C856B1 /* random_seed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random_seed.h; sourceTree = "<group>"; };
|
||||
DAB7AE731F3D755B00C856B1 /* strdup_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strdup_compat.h; sourceTree = "<group>"; };
|
||||
DAB7AE741F3D755B00C856B1 /* vasprintf_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vasprintf_compat.h; sourceTree = "<group>"; };
|
||||
DAB7AE761F3D755B00C856B1 /* libjson-c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libjson-c.a"; sourceTree = "<group>"; };
|
||||
DAB7AE971F3DDEE000C856B1 /* mpw-marshall-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-marshall-util.h"; sourceTree = "<group>"; };
|
||||
DAB7AE981F3DDEE000C856B1 /* mpw-marshall-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-marshall-util.c"; sourceTree = "<group>"; };
|
||||
DABB981515100B4000B05417 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
DABD360F1711E29400CF925C /* ui_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ui_background.png; sourceTree = "<group>"; };
|
||||
DABD36101711E29400CF925C /* ui_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ui_background@2x.png"; sourceTree = "<group>"; };
|
||||
@@ -1475,7 +1511,7 @@
|
||||
DABD38C11711E29700CF925C /* tip_location_teal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tip_location_teal@2x.png"; sourceTree = "<group>"; };
|
||||
DABD38C21711E29700CF925C /* tip_location_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tip_location_wood.png; sourceTree = "<group>"; };
|
||||
DABD38C31711E29700CF925C /* tip_location_wood@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tip_location_wood@2x.png"; sourceTree = "<group>"; };
|
||||
DABD38C81711E29700CF925C /* jquery-1.6.1.min.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "jquery-1.6.1.min.js"; sourceTree = "<group>"; };
|
||||
DABD38C81711E29700CF925C /* jquery-1.6.1.min.js */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = sourcecode.javascript; path = "jquery-1.6.1.min.js"; sourceTree = "<group>"; };
|
||||
DABD38C91711E29700CF925C /* keypad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = keypad.png; sourceTree = "<group>"; };
|
||||
DABD38CA1711E29700CF925C /* logo-bare.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "logo-bare.png"; sourceTree = "<group>"; };
|
||||
DABD38CB1711E29700CF925C /* menu-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "menu-icon.png"; sourceTree = "<group>"; };
|
||||
@@ -1514,7 +1550,7 @@
|
||||
DABD3BF01711E2DC00CF925C /* MPiOSConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPiOSConfig.h; sourceTree = "<group>"; };
|
||||
DABD3BF11711E2DC00CF925C /* MPiOSConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPiOSConfig.m; sourceTree = "<group>"; };
|
||||
DABD3BF31711E2DC00CF925C /* MasterPassword-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MasterPassword-Info.plist"; sourceTree = "<group>"; };
|
||||
DABD3BF81711E2DC00CF925C /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
DABD3BF81711E2DC00CF925C /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
DABD3BF91711E2DC00CF925C /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
||||
DABD3BFB1711E2DC00CF925C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
DABD3BFC1711E2DC00CF925C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
@@ -1528,7 +1564,7 @@
|
||||
DAC77CAD148291A600BCF976 /* libPearl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPearl.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAC77CB1148291A600BCF976 /* Pearl-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Pearl-Prefix.pch"; path = "../../Source/Pearl/Pearl-Prefix.pch"; sourceTree = "<group>"; };
|
||||
DACA29711705E1A8002C6C22 /* ciphers.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ciphers.plist; sourceTree = "<group>"; };
|
||||
DACA29721705E1A8002C6C22 /* dictionary.lst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dictionary.lst; sourceTree = "<group>"; };
|
||||
DACA29721705E1A8002C6C22 /* dictionary.lst */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = dictionary.lst; sourceTree = "<group>"; };
|
||||
DACA29771705E2BD002C6C22 /* JRSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JRSwizzle.h; sourceTree = "<group>"; };
|
||||
DACA298C1705E2BD002C6C22 /* JRSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JRSwizzle.m; sourceTree = "<group>"; };
|
||||
DACA29B51705E2DE002C6C22 /* UIColor+Expanded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Expanded.h"; sourceTree = "<group>"; };
|
||||
@@ -1545,7 +1581,6 @@
|
||||
DAE1EF2317E942DE00BC0086 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
DAE2726119CE9CB3007C5262 /* UITableViewCell+PearlDeque.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableViewCell+PearlDeque.m"; sourceTree = "<group>"; };
|
||||
DAE2726219CE9CB3007C5262 /* UITableViewCell+PearlDeque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableViewCell+PearlDeque.h"; sourceTree = "<group>"; };
|
||||
DAE8E65119867AB500416A0F /* libopensslcrypto-ios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libopensslcrypto-ios.a"; sourceTree = "<group>"; };
|
||||
DAEBC45214F6364500987BF6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||
DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Touches.m"; sourceTree = "<group>"; };
|
||||
DAEC85B218E3DD9A007FC0DF /* PearlUINavigationBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUINavigationBar.m; sourceTree = "<group>"; };
|
||||
@@ -1584,16 +1619,12 @@
|
||||
DAFE45F315039823003ABA7C /* PearlStrings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlStrings.m; sourceTree = "<group>"; };
|
||||
DAFE45F415039823003ABA7C /* PearlStringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlStringUtils.h; sourceTree = "<group>"; };
|
||||
DAFE45F515039823003ABA7C /* PearlStringUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlStringUtils.m; sourceTree = "<group>"; };
|
||||
DAFE45F815039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE45FB15039823003ABA7C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Pearl.strings; sourceTree = "<group>"; };
|
||||
DAFE45F815039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE45FB15039823003ABA7C /* en */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Pearl.strings; sourceTree = "<group>"; };
|
||||
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-Crypto.h"; sourceTree = "<group>"; };
|
||||
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlCryptUtils.h; sourceTree = "<group>"; };
|
||||
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlCryptUtils.m; sourceTree = "<group>"; };
|
||||
DAFE460015039823003ABA7C /* PearlKeyChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlKeyChain.h; sourceTree = "<group>"; };
|
||||
DAFE460115039823003ABA7C /* PearlKeyChain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlKeyChain.m; sourceTree = "<group>"; };
|
||||
DAFE460215039823003ABA7C /* PearlRSAKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRSAKey.h; sourceTree = "<group>"; };
|
||||
DAFE460315039823003ABA7C /* PearlRSAKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlRSAKey.m; sourceTree = "<group>"; };
|
||||
DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-UIKit-Dependencies.h"; sourceTree = "<group>"; };
|
||||
DAFE460915039823003ABA7C /* Pearl-UIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-UIKit.h"; sourceTree = "<group>"; };
|
||||
DAFE460A15039823003ABA7C /* PearlAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlAlert.h; sourceTree = "<group>"; };
|
||||
@@ -1604,10 +1635,6 @@
|
||||
DAFE460F15039823003ABA7C /* PearlBoxView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlBoxView.m; sourceTree = "<group>"; };
|
||||
DAFE461015039823003ABA7C /* PearlGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlGradientView.h; sourceTree = "<group>"; };
|
||||
DAFE461115039823003ABA7C /* PearlGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlGradientView.m; sourceTree = "<group>"; };
|
||||
DAFE461215039823003ABA7C /* PearlLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLayout.h; sourceTree = "<group>"; };
|
||||
DAFE461315039823003ABA7C /* PearlLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLayout.m; sourceTree = "<group>"; };
|
||||
DAFE461415039823003ABA7C /* PearlLayoutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlLayoutView.h; sourceTree = "<group>"; };
|
||||
DAFE461515039823003ABA7C /* PearlLayoutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLayoutView.m; sourceTree = "<group>"; };
|
||||
DAFE461615039823003ABA7C /* PearlMessageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlMessageView.h; sourceTree = "<group>"; };
|
||||
DAFE461715039823003ABA7C /* PearlMessageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlMessageView.m; sourceTree = "<group>"; };
|
||||
DAFE461815039823003ABA7C /* PearlRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRootViewController.h; sourceTree = "<group>"; };
|
||||
@@ -1620,7 +1647,7 @@
|
||||
DAFE461F15039823003ABA7C /* PearlUIUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUIUtils.m; sourceTree = "<group>"; };
|
||||
DAFE462015039823003ABA7C /* PearlValidatingTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlValidatingTextField.h; sourceTree = "<group>"; };
|
||||
DAFE462115039823003ABA7C /* PearlValidatingTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlValidatingTextField.m; sourceTree = "<group>"; };
|
||||
DAFE462415039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE462415039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE4A1115039824003ABA7C /* UIImage+PearlScaling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+PearlScaling.h"; sourceTree = "<group>"; };
|
||||
DAFE4A1215039824003ABA7C /* UIImage+PearlScaling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+PearlScaling.m"; sourceTree = "<group>"; };
|
||||
DAFE4A60150399FF003ABA7C /* PearlAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlAppDelegate.m; sourceTree = "<group>"; };
|
||||
@@ -1649,9 +1676,11 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAB7AE5D1F3D752900C856B1 /* libjson-c.a in Frameworks */,
|
||||
DA95B50C1C476B6A0067F5EF /* LocalAuthentication.framework in Frameworks */,
|
||||
DA2C3D651BD9612F001137B3 /* libz.tbd in Frameworks */,
|
||||
DA2C3D631BD96126001137B3 /* libc++.tbd in Frameworks */,
|
||||
DAB7AE771F3D755B00C856B1 /* libjson-c.a in Frameworks */,
|
||||
DAA1761B19D86D0D0044227B /* libAttributedMarkdown.a in Frameworks */,
|
||||
DA0CC5421EB57BD4009A8ED9 /* Crashlytics.framework in Frameworks */,
|
||||
DA32D03E19D11293004F3F0E /* libKCOrderedAccessorFix.a in Frameworks */,
|
||||
@@ -1730,6 +1759,8 @@
|
||||
93D39D4E713564B7654341B0 /* mpw-algorithm_v3.c */,
|
||||
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */,
|
||||
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */,
|
||||
DAB7AE981F3DDEE000C856B1 /* mpw-marshall-util.c */,
|
||||
DAB7AE971F3DDEE000C856B1 /* mpw-marshall-util.h */,
|
||||
DAA449D01EEC4B5800E7BDD5 /* mpw-marshall.c */,
|
||||
DAA449D11EEC4B5800E7BDD5 /* mpw-marshall.h */,
|
||||
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */,
|
||||
@@ -2018,6 +2049,7 @@
|
||||
DA5BFA47147E415C00F98B1E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE5C1F3D752900C856B1 /* libjson-c.a */,
|
||||
DA6701B716406A4100B61001 /* Accounts.framework */,
|
||||
DA6701DF16406BB400B61001 /* AdSupport.framework */,
|
||||
DA5BFA4E147E415C00F98B1E /* CoreData.framework */,
|
||||
@@ -2042,24 +2074,6 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA5E5C6317248959003798D8 /* lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5E5C6417248959003798D8 /* include */,
|
||||
DA7F2C5E1C48B70D00404A26 /* libopensslcrypto-ios-sim.a */,
|
||||
DAE8E65119867AB500416A0F /* libopensslcrypto-ios.a */,
|
||||
);
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA5E5C6417248959003798D8 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA25C6B31980D3C10046CDCF /* openssl */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAA141181922FED80032B392 /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2097,6 +2111,59 @@
|
||||
path = AttributedMarkdown;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE5E1F3D755B00C856B1 /* libjson-c-ios */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE5F1F3D755B00C856B1 /* include */,
|
||||
DAB7AE751F3D755B00C856B1 /* lib */,
|
||||
);
|
||||
name = "libjson-c-ios";
|
||||
path = "libjson-c/libjson-c-ios";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE5F1F3D755B00C856B1 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE601F3D755B00C856B1 /* json-c */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE601F3D755B00C856B1 /* json-c */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE611F3D755B00C856B1 /* arraylist.h */,
|
||||
DAB7AE621F3D755B00C856B1 /* bits.h */,
|
||||
DAB7AE631F3D755B00C856B1 /* debug.h */,
|
||||
DAB7AE641F3D755B00C856B1 /* json.h */,
|
||||
DAB7AE651F3D755B00C856B1 /* json_c_version.h */,
|
||||
DAB7AE661F3D755B00C856B1 /* json_config.h */,
|
||||
DAB7AE671F3D755B00C856B1 /* json_inttypes.h */,
|
||||
DAB7AE681F3D755B00C856B1 /* json_object.h */,
|
||||
DAB7AE691F3D755B00C856B1 /* json_object_iterator.h */,
|
||||
DAB7AE6A1F3D755B00C856B1 /* json_object_private.h */,
|
||||
DAB7AE6B1F3D755B00C856B1 /* json_pointer.h */,
|
||||
DAB7AE6C1F3D755B00C856B1 /* json_tokener.h */,
|
||||
DAB7AE6D1F3D755B00C856B1 /* json_util.h */,
|
||||
DAB7AE6E1F3D755B00C856B1 /* json_visit.h */,
|
||||
DAB7AE6F1F3D755B00C856B1 /* linkhash.h */,
|
||||
DAB7AE701F3D755B00C856B1 /* math_compat.h */,
|
||||
DAB7AE711F3D755B00C856B1 /* printbuf.h */,
|
||||
DAB7AE721F3D755B00C856B1 /* random_seed.h */,
|
||||
DAB7AE731F3D755B00C856B1 /* strdup_compat.h */,
|
||||
DAB7AE741F3D755B00C856B1 /* vasprintf_compat.h */,
|
||||
);
|
||||
path = "json-c";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE751F3D755B00C856B1 /* lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE761F3D755B00C856B1 /* libjson-c.a */,
|
||||
);
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DABD360D1711E29400CF925C /* Media */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2945,6 +3012,7 @@
|
||||
DACA22121705DDC5002C6C22 /* External */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE5E1F3D755B00C856B1 /* libjson-c-ios */,
|
||||
DA0978D81E9A81EE00F0BFE8 /* libsodium-ios */,
|
||||
DAA1759319D86C610044227B /* AttributedMarkdown */,
|
||||
DAFC5662172C57EC00CB5CC5 /* InAppSettingsKit */,
|
||||
@@ -3092,15 +3160,12 @@
|
||||
DAFE45FC15039823003ABA7C /* Pearl-Crypto */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5E5C6317248959003798D8 /* lib */,
|
||||
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */,
|
||||
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */,
|
||||
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */,
|
||||
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */,
|
||||
DA45711C1F572F1E00D54152 /* PearlCryptUtils.h */,
|
||||
DA45711B1F572F1E00D54152 /* PearlCryptUtils.m */,
|
||||
DAFE460015039823003ABA7C /* PearlKeyChain.h */,
|
||||
DAFE460115039823003ABA7C /* PearlKeyChain.m */,
|
||||
DAFE460215039823003ABA7C /* PearlRSAKey.h */,
|
||||
DAFE460315039823003ABA7C /* PearlRSAKey.m */,
|
||||
DAFE460615039823003ABA7C /* README */,
|
||||
);
|
||||
path = "Pearl-Crypto";
|
||||
@@ -3128,10 +3193,6 @@
|
||||
DA32D01819D046E1004F3F0E /* PearlFixedTableView.m */,
|
||||
DAFE461015039823003ABA7C /* PearlGradientView.h */,
|
||||
DAFE461115039823003ABA7C /* PearlGradientView.m */,
|
||||
DAFE461215039823003ABA7C /* PearlLayout.h */,
|
||||
DAFE461315039823003ABA7C /* PearlLayout.m */,
|
||||
DAFE461415039823003ABA7C /* PearlLayoutView.h */,
|
||||
DAFE461515039823003ABA7C /* PearlLayoutView.m */,
|
||||
DAFE461615039823003ABA7C /* PearlMessageView.h */,
|
||||
DAFE461715039823003ABA7C /* PearlMessageView.m */,
|
||||
DACE2F6919BA6A2A0010F92E /* PearlMutableStaticTableViewController.h */,
|
||||
@@ -3227,7 +3288,6 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA25C6B41980D3C50046CDCF /* openssl in Headers */,
|
||||
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */,
|
||||
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */,
|
||||
DAFE4A1715039824003ABA7C /* NSString+PearlSEL.h in Headers */,
|
||||
@@ -3249,9 +3309,7 @@
|
||||
DAFE4A2F15039824003ABA7C /* PearlStringUtils.h in Headers */,
|
||||
DA2CA4E018D28859007798F8 /* NSTimer+PearlBlock.h in Headers */,
|
||||
DAFE4A3315039824003ABA7C /* Pearl-Crypto.h in Headers */,
|
||||
DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */,
|
||||
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */,
|
||||
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */,
|
||||
DAE2726419CE9CB3007C5262 /* UITableViewCell+PearlDeque.h in Headers */,
|
||||
DACE2F6E19BA6A2A0010F92E /* UIView+FontScale.h in Headers */,
|
||||
DA32D01B19D046E1004F3F0E /* PearlFixedTableView.h in Headers */,
|
||||
@@ -3263,8 +3321,6 @@
|
||||
DAFE4A4215039824003ABA7C /* PearlBoxView.h in Headers */,
|
||||
DAEFB01F19BCBD9E00525079 /* UIView+LayoutGone.h in Headers */,
|
||||
DAFE4A4415039824003ABA7C /* PearlGradientView.h in Headers */,
|
||||
DAFE4A4615039824003ABA7C /* PearlLayout.h in Headers */,
|
||||
DAFE4A4815039824003ABA7C /* PearlLayoutView.h in Headers */,
|
||||
DAFE4A4A15039824003ABA7C /* PearlMessageView.h in Headers */,
|
||||
DACE2F6619BA6A0A0010F92E /* PearlProfiler.h in Headers */,
|
||||
DAFE4A4C15039824003ABA7C /* PearlRootViewController.h in Headers */,
|
||||
@@ -3309,6 +3365,36 @@
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXLegacyTarget section */
|
||||
DAB7AE3D1F3D464A00C856B1 /* libjson-c-ios */ = {
|
||||
isa = PBXLegacyTarget;
|
||||
buildArgumentsString = "$(ACTION)";
|
||||
buildConfigurationList = DAB7AE411F3D464A00C856B1 /* Build configuration list for PBXLegacyTarget "libjson-c-ios" */;
|
||||
buildPhases = (
|
||||
);
|
||||
buildToolPath = "Scripts/build_libjson-c-ios";
|
||||
buildWorkingDirectory = "";
|
||||
dependencies = (
|
||||
);
|
||||
name = "libjson-c-ios";
|
||||
passBuildSettingsInEnvironment = 1;
|
||||
productName = "libjson-c";
|
||||
};
|
||||
DAB7AE471F3D468300C856B1 /* libsodium-ios */ = {
|
||||
isa = PBXLegacyTarget;
|
||||
buildArgumentsString = "$(ACTION)";
|
||||
buildConfigurationList = DAB7AE481F3D468300C856B1 /* Build configuration list for PBXLegacyTarget "libsodium-ios" */;
|
||||
buildPhases = (
|
||||
);
|
||||
buildToolPath = "Scripts/build_libsodium-ios";
|
||||
dependencies = (
|
||||
);
|
||||
name = "libsodium-ios";
|
||||
passBuildSettingsInEnvironment = 1;
|
||||
productName = "libsodium-ios";
|
||||
};
|
||||
/* End PBXLegacyTarget section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DA32D01F19D111C6004F3F0E /* KCOrderedAccessorFix */ = {
|
||||
isa = PBXNativeTarget;
|
||||
@@ -3332,7 +3418,6 @@
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
|
||||
buildPhases = (
|
||||
DA8D88E019DA412A00B189D0 /* Run Script: genassets */,
|
||||
DA0E86A81E9BED2C00F4D60E /* Run Script: libsodium/dist-build/ios.sh */,
|
||||
DA5BFA40147E415C00F98B1E /* Sources */,
|
||||
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
||||
DA5BFA42147E415C00F98B1E /* Resources */,
|
||||
@@ -3342,6 +3427,8 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DAB7AE4E1F3D618700C856B1 /* PBXTargetDependency */,
|
||||
DAB7AE501F3D618700C856B1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = MasterPassword;
|
||||
productName = MasterPassword;
|
||||
@@ -3403,6 +3490,7 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DAC77CB7148291A600BCF976 /* Build configuration list for PBXNativeTarget "Pearl" */;
|
||||
buildPhases = (
|
||||
DAB7AE4C1F3D56AD00C856B1 /* ShellScript */,
|
||||
DAC77CAB148291A600BCF976 /* Headers */,
|
||||
DAC77CA9148291A600BCF976 /* Sources */,
|
||||
DAC77CAA148291A600BCF976 /* Frameworks */,
|
||||
@@ -3468,6 +3556,16 @@
|
||||
CreatedOnToolsVersion = 6.0;
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
DAB7AE3D1F3D464A00C856B1 = {
|
||||
CreatedOnToolsVersion = 8.3.3;
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
DAB7AE471F3D468300C856B1 = {
|
||||
CreatedOnToolsVersion = 8.3.3;
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
DAC6325C1486805C0075AEA5 = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
@@ -3588,6 +3686,8 @@
|
||||
DAFC5654172C573B00CB5CC5 /* InAppSettingsKit */,
|
||||
DA32D01F19D111C6004F3F0E /* KCOrderedAccessorFix */,
|
||||
DAA1757C19D86BE70044227B /* AttributedMarkdown */,
|
||||
DAB7AE471F3D468300C856B1 /* libsodium-ios */,
|
||||
DAB7AE3D1F3D464A00C856B1 /* libjson-c-ios */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -3783,21 +3883,6 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
DA0E86A81E9BED2C00F4D60E /* Run Script: libsodium/dist-build/ios.sh */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script: libsodium/dist-build/ios.sh";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = "/bin/sh -e";
|
||||
shellScript = "cd External/libsodium\n[[ -d libsodium-ios ]] && exit\n\n# Xcode misinterpretes autogen.sh's stderr output as errors so we try to silence it.\n[[ -e configure ]] || { err=$(./autogen.sh 2>&1 >&3); } 3>&1 || { x=$?; echo >&2 \"$err\"; exit $x; }\n./dist-build/ios.sh";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -3828,6 +3913,19 @@
|
||||
shellScript = "exec Scripts/genassets";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DAB7AE4C1F3D56AD00C856B1 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "";
|
||||
};
|
||||
DAD3125D155288AA00A3F9ED /* Run Script: Fabric */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -3890,6 +3988,7 @@
|
||||
DA0CC58E1EB6B030009A8ED9 /* MPSiteQuestionEntity+CoreDataClass.m in Sources */,
|
||||
93D39A5FF670957C0AF8298D /* MPSiteCell.m in Sources */,
|
||||
93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */,
|
||||
DAB7AE991F3DDEE000C856B1 /* mpw-marshall-util.c in Sources */,
|
||||
DA95B50F1C4776F00067F5EF /* NSMutableSet+Pearl.m in Sources */,
|
||||
93D394B5036C882B33C71872 /* MPSitesSegue.m in Sources */,
|
||||
DA0CC5911EB6B030009A8ED9 /* MPStoredSiteEntity+CoreDataProperties.m in Sources */,
|
||||
@@ -3904,6 +4003,7 @@
|
||||
93D39D8F78978196D6ABDEDE /* MPNavigationController.m in Sources */,
|
||||
93D3939661CE37180AF7CD6A /* MPStoreViewController.m in Sources */,
|
||||
93D390C1B93F9D3AE37DD0A5 /* MPAnswersViewController.m in Sources */,
|
||||
DA45711D1F572F1E00D54152 /* PearlCryptUtils.m in Sources */,
|
||||
93D399D7E08A142776A74CB8 /* MPOverlayViewController.m in Sources */,
|
||||
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */,
|
||||
93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */,
|
||||
@@ -3964,18 +4064,14 @@
|
||||
DAFE4A2B15039824003ABA7C /* PearlObjectUtils.m in Sources */,
|
||||
DAFE4A2E15039824003ABA7C /* PearlStrings.m in Sources */,
|
||||
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */,
|
||||
DAFE4A3515039824003ABA7C /* PearlCryptUtils.m in Sources */,
|
||||
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
|
||||
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */,
|
||||
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */,
|
||||
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */,
|
||||
DAFE4A3F15039824003ABA7C /* PearlAlert.m in Sources */,
|
||||
DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */,
|
||||
DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */,
|
||||
DAFE4A4515039824003ABA7C /* PearlGradientView.m in Sources */,
|
||||
DAFE4A4715039824003ABA7C /* PearlLayout.m in Sources */,
|
||||
DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */,
|
||||
DAFE4A4915039824003ABA7C /* PearlLayoutView.m in Sources */,
|
||||
DAE2726319CE9CB3007C5262 /* UITableViewCell+PearlDeque.m in Sources */,
|
||||
DAFE4A4B15039824003ABA7C /* PearlMessageView.m in Sources */,
|
||||
DACE2F6519BA6A0A0010F92E /* PearlProfiler.m in Sources */,
|
||||
@@ -4051,6 +4147,19 @@
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
DAB7AE4E1F3D618700C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DAB7AE471F3D468300C856B1 /* libsodium-ios */;
|
||||
targetProxy = DAB7AE4D1F3D618700C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAB7AE501F3D618700C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DAB7AE3D1F3D464A00C856B1 /* libjson-c-ios */;
|
||||
targetProxy = DAB7AE4F1F3D618700C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
DA0CC4F51EAB99BA009A8ED9 /* IASKLocalizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
@@ -4174,6 +4283,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libsodium/libsodium-ios/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libjson-c/libjson-c-ios/include\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
@@ -4212,8 +4323,12 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-ios/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
OTHER_CFLAGS = "-DHAS_SODIUM=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
|
||||
SKIP_INSTALL = NO;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
@@ -4356,6 +4471,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libsodium/libsodium-ios/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libjson-c/libjson-c-ios/include\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
@@ -4444,6 +4561,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libsodium/libsodium-ios/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libjson-c/libjson-c-ios/include\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
@@ -4480,8 +4599,12 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-ios/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
OTHER_CFLAGS = "-DHAS_SODIUM=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
|
||||
SKIP_INSTALL = NO;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
@@ -4510,8 +4633,12 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-ios/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
OTHER_CFLAGS = "-DHAS_SODIUM=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
|
||||
SKIP_INSTALL = NO;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
@@ -4535,6 +4662,128 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAB7AE3E1F3D464A00C856B1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAB7AE3F1F3D464A00C856B1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAB7AE401F3D464A00C856B1 /* Test */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DAB7AE491F3D468300C856B1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAB7AE4A1F3D468300C856B1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAB7AE4B1F3D468300C856B1 /* Test */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DAC632661486805C0075AEA5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -4650,6 +4899,26 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DAB7AE411F3D464A00C856B1 /* Build configuration list for PBXLegacyTarget "libjson-c-ios" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DAB7AE3E1F3D464A00C856B1 /* Debug */,
|
||||
DAB7AE3F1F3D464A00C856B1 /* Release */,
|
||||
DAB7AE401F3D464A00C856B1 /* Test */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DAB7AE481F3D468300C856B1 /* Build configuration list for PBXLegacyTarget "libsodium-ios" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DAB7AE491F3D468300C856B1 /* Debug */,
|
||||
DAB7AE4A1F3D468300C856B1 /* Release */,
|
||||
DAB7AE4B1F3D468300C856B1 /* Test */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DAC632651486805C0075AEA5 /* Build configuration list for PBXNativeTarget "uicolor-utilities" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
DA0979681E9A834C00F0BFE8 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979571E9A824700F0BFE8 /* libsodium.a */; };
|
||||
DA0CC53E1EB57B69009A8ED9 /* Fabric.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA0CC53D1EB57B69009A8ED9 /* Fabric.plist */; };
|
||||
DA0CC5591EB6AE45009A8ED9 /* MasterPassword.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC54F1EB6AE45009A8ED9 /* MasterPassword.xcdatamodeld */; };
|
||||
DA1000801998A4C6002B873F /* openssl in Headers */ = {isa = PBXBuildFile; fileRef = DAE8E65719867AF500416A0F /* openssl */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA16B341170661DB000A0EAB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B340170661DB000A0EAB /* Carbon.framework */; };
|
||||
DA16B342170661E0000A0EAB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; };
|
||||
DA16B344170661EE000A0EAB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B343170661EE000A0EAB /* Cocoa.framework */; };
|
||||
@@ -78,6 +77,7 @@
|
||||
DA3B8453190FC86F00246EEA /* NSManagedObject+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3B8451190FC86F00246EEA /* NSManagedObject+Pearl.h */; };
|
||||
DA3B8456190FC89700246EEA /* MPFixable.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B8454190FC89700246EEA /* MPFixable.m */; };
|
||||
DA3BCFCD19BD09E0006B2681 /* SourceCodePro-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA3BCFCC19BD09E0006B2681 /* SourceCodePro-Regular.otf */; };
|
||||
DA4571201F572F3200D54152 /* PearlCryptUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DA45711E1F572F3200D54152 /* PearlCryptUtils.m */; };
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; };
|
||||
DA4DAE941A7D8117003E5423 /* MPAlgorithmV3.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE921A7D8117003E5423 /* MPAlgorithmV3.m */; };
|
||||
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE931A7D8117003E5423 /* MPTypes.m */; };
|
||||
@@ -117,7 +117,6 @@
|
||||
DA8ED895192906920099B726 /* PearlTween.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8ED891192906920099B726 /* PearlTween.m */; };
|
||||
DA8ED896192906920099B726 /* PearlTween.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED892192906920099B726 /* PearlTween.h */; };
|
||||
DA8ED897192906920099B726 /* map-macro.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED894192906920099B726 /* map-macro.h */; };
|
||||
DA92614B1BE1A4EA00369DE5 /* libopensslcrypto-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */; };
|
||||
DA9261511BE1A86700369DE5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA92614F1BE1A86700369DE5 /* SystemConfiguration.framework */; };
|
||||
DA9261521BE1A86700369DE5 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9261501BE1A86700369DE5 /* Fabric.framework */; };
|
||||
DA9261541BE1A88900369DE5 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9261531BE1A88900369DE5 /* libc++.tbd */; };
|
||||
@@ -130,6 +129,10 @@
|
||||
DAADCC4B19FB000C00987B1D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; };
|
||||
DAADCC6919FB007F00987B1D /* NSManagedObjectModel+KCOrderedAccessorFix.m in Sources */ = {isa = PBXBuildFile; fileRef = DAADCC6719FB007F00987B1D /* NSManagedObjectModel+KCOrderedAccessorFix.m */; };
|
||||
DAADCC6A19FB00B500987B1D /* libKCOrderedAccessorFix.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAADCC5019FB006500987B1D /* libKCOrderedAccessorFix.a */; };
|
||||
DAAF16661F5CA3240013B8AE /* mpw-cli-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DAAF16631F5897EA0013B8AE /* mpw-cli-util.c */; };
|
||||
DAB7AE5A1F3D74E700C856B1 /* libjson-c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAB7AE591F3D74E700C856B1 /* libjson-c.a */; };
|
||||
DAB7AE5B1F3D750B00C856B1 /* libjson-c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAB7AE591F3D74E700C856B1 /* libjson-c.a */; };
|
||||
DAB7AE941F3D757B00C856B1 /* libjson-c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAB7AE901F3D757B00C856B1 /* libjson-c.a */; };
|
||||
DAC6326D148680650075AEA5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||
DACA26FE1705DF81002C6C22 /* logo-bare.png in Resources */ = {isa = PBXBuildFile; fileRef = DACA241C1705DF7D002C6C22 /* logo-bare.png */; };
|
||||
@@ -216,12 +219,8 @@
|
||||
DAFE4A2F15039824003ABA7C /* PearlStringUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45F415039823003ABA7C /* PearlStringUtils.h */; };
|
||||
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45F515039823003ABA7C /* PearlStringUtils.m */; };
|
||||
DAFE4A3315039824003ABA7C /* Pearl-Crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */; };
|
||||
DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */; };
|
||||
DAFE4A3515039824003ABA7C /* PearlCryptUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */; };
|
||||
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460015039823003ABA7C /* PearlKeyChain.h */; };
|
||||
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460115039823003ABA7C /* PearlKeyChain.m */; };
|
||||
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460215039823003ABA7C /* PearlRSAKey.h */; };
|
||||
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460315039823003ABA7C /* PearlRSAKey.m */; };
|
||||
DAFE4A5A1503982E003ABA7C /* Pearl.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAFE45FA15039823003ABA7C /* Pearl.strings */; };
|
||||
DAFE4A63150399FF003ABA86 /* NSObject+PearlKVO.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA85 /* NSObject+PearlKVO.m */; };
|
||||
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA87 /* NSObject+PearlKVO.h */; };
|
||||
@@ -230,6 +229,48 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
DAB7AE341F3D423600C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DA5B0B611F3D416500B663F0;
|
||||
remoteInfo = "libsodium-osx";
|
||||
};
|
||||
DAB7AE361F3D423D00C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DA5B0B611F3D416500B663F0;
|
||||
remoteInfo = "libsodium-osx";
|
||||
};
|
||||
DAB7AE381F3D424200C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DA5B0B611F3D416500B663F0;
|
||||
remoteInfo = "libsodium-osx";
|
||||
};
|
||||
DAB7AE3A1F3D424700C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DA5B0B611F3D416500B663F0;
|
||||
remoteInfo = "libsodium-osx";
|
||||
};
|
||||
DAB7AE511F3D649400C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DAB7AE421F3D466D00C856B1;
|
||||
remoteInfo = "libjson-c";
|
||||
};
|
||||
DAB7AE571F3D64A600C856B1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DAB7AE421F3D466D00C856B1;
|
||||
remoteInfo = "libjson-c";
|
||||
};
|
||||
DABFA071176E3FDF00E83589 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DAD9B5E1176299B9001835F9 /* MasterPassword-Mac-LoginHelper.xcodeproj */;
|
||||
@@ -453,6 +494,11 @@
|
||||
DA3B8454190FC89700246EEA /* MPFixable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPFixable.m; sourceTree = "<group>"; };
|
||||
DA3B8455190FC89700246EEA /* MPFixable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFixable.h; sourceTree = "<group>"; };
|
||||
DA3BCFCC19BD09E0006B2681 /* SourceCodePro-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-Regular.otf"; sourceTree = "<group>"; };
|
||||
DA456CA21F5307B700D54152 /* blf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blf.h; sourceTree = "<group>"; };
|
||||
DA4571171F552C9500D54152 /* bcrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bcrypt.h; sourceTree = "<group>"; };
|
||||
DA4571181F552C9500D54152 /* blowfish.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blowfish.h; sourceTree = "<group>"; };
|
||||
DA45711E1F572F3200D54152 /* PearlCryptUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlCryptUtils.m; sourceTree = "<group>"; };
|
||||
DA45711F1F572F3200D54152 /* PearlCryptUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlCryptUtils.h; sourceTree = "<group>"; };
|
||||
DA4DAE911A7D8117003E5423 /* MPAlgorithmV3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV3.h; sourceTree = "<group>"; };
|
||||
DA4DAE921A7D8117003E5423 /* MPAlgorithmV3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV3.m; sourceTree = "<group>"; };
|
||||
DA4DAE931A7D8117003E5423 /* MPTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTypes.m; sourceTree = "<group>"; };
|
||||
@@ -488,7 +534,7 @@
|
||||
DA5E5CB51724A667003798D8 /* MPMacConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMacConfig.h; sourceTree = "<group>"; };
|
||||
DA5E5CB61724A667003798D8 /* MPMacConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacConfig.m; sourceTree = "<group>"; };
|
||||
DA5E5CBA1724A667003798D8 /* MasterPassword-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MasterPassword-Info.plist"; sourceTree = "<group>"; };
|
||||
DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
DA5E5CC31724A667003798D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
DA5E5CC51724A667003798D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
DA5E5CC61724A667003798D8 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
@@ -929,6 +975,30 @@
|
||||
DAADCC5019FB006500987B1D /* libKCOrderedAccessorFix.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKCOrderedAccessorFix.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAADCC6619FB007F00987B1D /* NSManagedObjectModel+KCOrderedAccessorFix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectModel+KCOrderedAccessorFix.h"; sourceTree = "<group>"; };
|
||||
DAADCC6719FB007F00987B1D /* NSManagedObjectModel+KCOrderedAccessorFix.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectModel+KCOrderedAccessorFix.m"; sourceTree = "<group>"; };
|
||||
DAAF16631F5897EA0013B8AE /* mpw-cli-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-cli-util.c"; sourceTree = "<group>"; };
|
||||
DAAF16641F5897EA0013B8AE /* mpw-cli-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-cli-util.h"; sourceTree = "<group>"; };
|
||||
DAB7AE591F3D74E700C856B1 /* libjson-c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libjson-c.a"; path = "External/libjson-c/libjson-c-osx/lib/libjson-c.a"; sourceTree = "<group>"; };
|
||||
DAB7AE7B1F3D757B00C856B1 /* arraylist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arraylist.h; sourceTree = "<group>"; };
|
||||
DAB7AE7C1F3D757B00C856B1 /* bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bits.h; sourceTree = "<group>"; };
|
||||
DAB7AE7D1F3D757B00C856B1 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
|
||||
DAB7AE7E1F3D757B00C856B1 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = "<group>"; };
|
||||
DAB7AE7F1F3D757B00C856B1 /* json_c_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_c_version.h; sourceTree = "<group>"; };
|
||||
DAB7AE801F3D757B00C856B1 /* json_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_config.h; sourceTree = "<group>"; };
|
||||
DAB7AE811F3D757B00C856B1 /* json_inttypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_inttypes.h; sourceTree = "<group>"; };
|
||||
DAB7AE821F3D757B00C856B1 /* json_object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_object.h; sourceTree = "<group>"; };
|
||||
DAB7AE831F3D757B00C856B1 /* json_object_iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_object_iterator.h; sourceTree = "<group>"; };
|
||||
DAB7AE841F3D757B00C856B1 /* json_object_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_object_private.h; sourceTree = "<group>"; };
|
||||
DAB7AE851F3D757B00C856B1 /* json_pointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_pointer.h; sourceTree = "<group>"; };
|
||||
DAB7AE861F3D757B00C856B1 /* json_tokener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_tokener.h; sourceTree = "<group>"; };
|
||||
DAB7AE871F3D757B00C856B1 /* json_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_util.h; sourceTree = "<group>"; };
|
||||
DAB7AE881F3D757B00C856B1 /* json_visit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_visit.h; sourceTree = "<group>"; };
|
||||
DAB7AE891F3D757B00C856B1 /* linkhash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linkhash.h; sourceTree = "<group>"; };
|
||||
DAB7AE8A1F3D757B00C856B1 /* math_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = math_compat.h; sourceTree = "<group>"; };
|
||||
DAB7AE8B1F3D757B00C856B1 /* printbuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printbuf.h; sourceTree = "<group>"; };
|
||||
DAB7AE8C1F3D757B00C856B1 /* random_seed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random_seed.h; sourceTree = "<group>"; };
|
||||
DAB7AE8D1F3D757B00C856B1 /* strdup_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strdup_compat.h; sourceTree = "<group>"; };
|
||||
DAB7AE8E1F3D757B00C856B1 /* vasprintf_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vasprintf_compat.h; sourceTree = "<group>"; };
|
||||
DAB7AE901F3D757B00C856B1 /* libjson-c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libjson-c.a"; sourceTree = "<group>"; };
|
||||
DABB981515100B4000B05417 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
DAC6326C148680650075AEA5 /* libjrswizzle.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjrswizzle.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAC632871486D95D0075AEA5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
@@ -977,7 +1047,7 @@
|
||||
DACA268E1705DF81002C6C22 /* SourceCodePro-ExtraLight.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-ExtraLight.otf"; sourceTree = "<group>"; };
|
||||
DACA268F1705DF81002C6C22 /* SourceCodePro-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-Black.otf"; sourceTree = "<group>"; };
|
||||
DACA29711705E1A8002C6C22 /* ciphers.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = ciphers.plist; sourceTree = "<group>"; };
|
||||
DACA29721705E1A8002C6C22 /* dictionary.lst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dictionary.lst; sourceTree = "<group>"; };
|
||||
DACA29721705E1A8002C6C22 /* dictionary.lst */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = dictionary.lst; sourceTree = "<group>"; };
|
||||
DACA29771705E2BD002C6C22 /* JRSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JRSwizzle.h; sourceTree = "<group>"; };
|
||||
DACA298C1705E2BD002C6C22 /* JRSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JRSwizzle.m; sourceTree = "<group>"; };
|
||||
DACBFCDB1C59B22E007EF90F /* NSMutableSet+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableSet+Pearl.h"; sourceTree = "<group>"; };
|
||||
@@ -995,8 +1065,6 @@
|
||||
DAD0C60019FD6034009CB08D /* icon.sketch */ = {isa = PBXFileReference; lastKnownFileType = file; path = icon.sketch; sourceTree = "<group>"; };
|
||||
DAD9B5E1176299B9001835F9 /* MasterPassword-Mac-LoginHelper.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MasterPassword-Mac-LoginHelper.xcodeproj"; path = "MasterPassword-Mac-LoginHelper/MasterPassword-Mac-LoginHelper.xcodeproj"; sourceTree = "<group>"; };
|
||||
DAD9B5EF1762CAA4001835F9 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
|
||||
DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libopensslcrypto-osx.a"; sourceTree = "<group>"; };
|
||||
DAE8E65719867AF500416A0F /* openssl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = openssl; sourceTree = "<group>"; };
|
||||
DAEBC45214F6364500987BF6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||
DAF4EF52190A828100023C90 /* Exo2.0-Thin.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Thin.otf"; sourceTree = "<group>"; };
|
||||
DAF4EF53190A828100023C90 /* Exo2.0-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Regular.otf"; sourceTree = "<group>"; };
|
||||
@@ -1030,16 +1098,12 @@
|
||||
DAFE45F315039823003ABA7C /* PearlStrings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlStrings.m; sourceTree = "<group>"; };
|
||||
DAFE45F415039823003ABA7C /* PearlStringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlStringUtils.h; sourceTree = "<group>"; };
|
||||
DAFE45F515039823003ABA7C /* PearlStringUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlStringUtils.m; sourceTree = "<group>"; };
|
||||
DAFE45F815039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE45FB15039823003ABA7C /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Pearl.strings; sourceTree = "<group>"; };
|
||||
DAFE45F815039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE45FB15039823003ABA7C /* en */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Pearl.strings; sourceTree = "<group>"; };
|
||||
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-Crypto.h"; sourceTree = "<group>"; };
|
||||
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlCryptUtils.h; sourceTree = "<group>"; };
|
||||
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlCryptUtils.m; sourceTree = "<group>"; };
|
||||
DAFE460015039823003ABA7C /* PearlKeyChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlKeyChain.h; sourceTree = "<group>"; };
|
||||
DAFE460115039823003ABA7C /* PearlKeyChain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlKeyChain.m; sourceTree = "<group>"; };
|
||||
DAFE460215039823003ABA7C /* PearlRSAKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRSAKey.h; sourceTree = "<group>"; };
|
||||
DAFE460315039823003ABA7C /* PearlRSAKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlRSAKey.m; sourceTree = "<group>"; };
|
||||
DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 1; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
DAFE4A63150399FF003ABA85 /* NSObject+PearlKVO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PearlKVO.m"; sourceTree = "<group>"; };
|
||||
DAFE4A63150399FF003ABA87 /* NSObject+PearlKVO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PearlKVO.h"; sourceTree = "<group>"; };
|
||||
DAFE4A63150399FF003ABA91 /* NSDateFormatter+RFC3339.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDateFormatter+RFC3339.m"; sourceTree = "<group>"; };
|
||||
@@ -1051,6 +1115,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAB7AE5A1F3D74E700C856B1 /* libjson-c.a in Frameworks */,
|
||||
DA1C7AAF1F1A8F24009A3551 /* libsodium.a in Frameworks */,
|
||||
DA1C7AB01F1A8F24009A3551 /* libxml2.tbd in Frameworks */,
|
||||
);
|
||||
@@ -1069,9 +1134,11 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAB7AE5B1F3D750B00C856B1 /* libjson-c.a in Frameworks */,
|
||||
DA9261561BE1A89600369DE5 /* libz.tbd in Frameworks */,
|
||||
DA9261541BE1A88900369DE5 /* libc++.tbd in Frameworks */,
|
||||
DAADCC6A19FB00B500987B1D /* libKCOrderedAccessorFix.a in Frameworks */,
|
||||
DAB7AE941F3D757B00C856B1 /* libjson-c.a in Frameworks */,
|
||||
DADD5DFA1EA173B0005E7D96 /* libsodium.a in Frameworks */,
|
||||
DA9261521BE1A86700369DE5 /* Fabric.framework in Frameworks */,
|
||||
DA9261511BE1A86700369DE5 /* SystemConfiguration.framework in Frameworks */,
|
||||
@@ -1116,7 +1183,6 @@
|
||||
DAADCC4B19FB000C00987B1D /* QuartzCore.framework in Frameworks */,
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */,
|
||||
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */,
|
||||
DA92614B1BE1A4EA00369DE5 /* libopensslcrypto-osx.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1225,7 +1291,12 @@
|
||||
DA1C7AB71F1A8F6E009A3551 /* cli */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA4571171F552C9500D54152 /* bcrypt.h */,
|
||||
DA456CA21F5307B700D54152 /* blf.h */,
|
||||
DA4571181F552C9500D54152 /* blowfish.h */,
|
||||
DA1C7AB81F1A8F6E009A3551 /* mpw-bench.c */,
|
||||
DAAF16631F5897EA0013B8AE /* mpw-cli-util.c */,
|
||||
DAAF16641F5897EA0013B8AE /* mpw-cli-util.h */,
|
||||
DA1C7AB91F1A8F6E009A3551 /* mpw-cli.c */,
|
||||
DA1C7ABA1F1A8F6E009A3551 /* mpw-tests-util.c */,
|
||||
DA1C7ABB1F1A8F6E009A3551 /* mpw-tests-util.h */,
|
||||
@@ -1284,6 +1355,7 @@
|
||||
DA5BFA47147E415C00F98B1E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE591F3D74E700C856B1 /* libjson-c.a */,
|
||||
DA09745D1E99586600F0BFE8 /* libxml2.tbd */,
|
||||
DA6701B716406A4100B61001 /* Accounts.framework */,
|
||||
DA16B340170661DB000A0EAB /* Carbon.framework */,
|
||||
@@ -1303,15 +1375,6 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA5E5C7917248AA1003798D8 /* lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAEB938518AB0FFD000490CC /* include */,
|
||||
DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */,
|
||||
);
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA5E5C961724A667003798D8 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1865,6 +1928,59 @@
|
||||
path = KCOrderedAccessorFix;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE781F3D757B00C856B1 /* libjson-c-osx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE791F3D757B00C856B1 /* include */,
|
||||
DAB7AE8F1F3D757B00C856B1 /* lib */,
|
||||
);
|
||||
name = "libjson-c-osx";
|
||||
path = "libjson-c/libjson-c-osx";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE791F3D757B00C856B1 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE7A1F3D757B00C856B1 /* json-c */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE7A1F3D757B00C856B1 /* json-c */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE7B1F3D757B00C856B1 /* arraylist.h */,
|
||||
DAB7AE7C1F3D757B00C856B1 /* bits.h */,
|
||||
DAB7AE7D1F3D757B00C856B1 /* debug.h */,
|
||||
DAB7AE7E1F3D757B00C856B1 /* json.h */,
|
||||
DAB7AE7F1F3D757B00C856B1 /* json_c_version.h */,
|
||||
DAB7AE801F3D757B00C856B1 /* json_config.h */,
|
||||
DAB7AE811F3D757B00C856B1 /* json_inttypes.h */,
|
||||
DAB7AE821F3D757B00C856B1 /* json_object.h */,
|
||||
DAB7AE831F3D757B00C856B1 /* json_object_iterator.h */,
|
||||
DAB7AE841F3D757B00C856B1 /* json_object_private.h */,
|
||||
DAB7AE851F3D757B00C856B1 /* json_pointer.h */,
|
||||
DAB7AE861F3D757B00C856B1 /* json_tokener.h */,
|
||||
DAB7AE871F3D757B00C856B1 /* json_util.h */,
|
||||
DAB7AE881F3D757B00C856B1 /* json_visit.h */,
|
||||
DAB7AE891F3D757B00C856B1 /* linkhash.h */,
|
||||
DAB7AE8A1F3D757B00C856B1 /* math_compat.h */,
|
||||
DAB7AE8B1F3D757B00C856B1 /* printbuf.h */,
|
||||
DAB7AE8C1F3D757B00C856B1 /* random_seed.h */,
|
||||
DAB7AE8D1F3D757B00C856B1 /* strdup_compat.h */,
|
||||
DAB7AE8E1F3D757B00C856B1 /* vasprintf_compat.h */,
|
||||
);
|
||||
path = "json-c";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7AE8F1F3D757B00C856B1 /* lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE901F3D757B00C856B1 /* libjson-c.a */,
|
||||
);
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC77CAF148291A600BCF976 /* Pearl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1879,6 +1995,7 @@
|
||||
DACA22121705DDC5002C6C22 /* External */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7AE781F3D757B00C856B1 /* libjson-c-osx */,
|
||||
DA0979181E9A824700F0BFE8 /* libsodium-osx */,
|
||||
DACA29751705E2BD002C6C22 /* jrswizzle */,
|
||||
DAADCC6819FB007F00987B1D /* KCOrderedAccessorFix */,
|
||||
@@ -2027,14 +2144,6 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAEB938518AB0FFD000490CC /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAE8E65719867AF500416A0F /* openssl */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFE45D715039823003ABA7C /* Pearl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2114,15 +2223,12 @@
|
||||
DAFE45FC15039823003ABA7C /* Pearl-Crypto */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5E5C7917248AA1003798D8 /* lib */,
|
||||
DAFE45FD15039823003ABA7C /* Pearl-Crypto.h */,
|
||||
DA30E9D115722EE500A68B4C /* Pearl-Crypto.m */,
|
||||
DAFE45FE15039823003ABA7C /* PearlCryptUtils.h */,
|
||||
DAFE45FF15039823003ABA7C /* PearlCryptUtils.m */,
|
||||
DA45711F1F572F3200D54152 /* PearlCryptUtils.h */,
|
||||
DA45711E1F572F3200D54152 /* PearlCryptUtils.m */,
|
||||
DAFE460015039823003ABA7C /* PearlKeyChain.h */,
|
||||
DAFE460115039823003ABA7C /* PearlKeyChain.m */,
|
||||
DAFE460215039823003ABA7C /* PearlRSAKey.h */,
|
||||
DAFE460315039823003ABA7C /* PearlRSAKey.m */,
|
||||
DAFE460615039823003ABA7C /* README */,
|
||||
);
|
||||
path = "Pearl-Crypto";
|
||||
@@ -2144,7 +2250,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA89D4EC1A51EABD00AC64D7 /* Pearl-Cocoa.h in Headers */,
|
||||
DA1000801998A4C6002B873F /* openssl in Headers */,
|
||||
DA2CA4F218D323D3007798F8 /* NSTimer+PearlBlock.h in Headers */,
|
||||
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */,
|
||||
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */,
|
||||
@@ -2166,9 +2271,7 @@
|
||||
DAFE4A2D15039824003ABA7C /* PearlStrings.h in Headers */,
|
||||
DAFE4A2F15039824003ABA7C /* PearlStringUtils.h in Headers */,
|
||||
DAFE4A3315039824003ABA7C /* Pearl-Crypto.h in Headers */,
|
||||
DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */,
|
||||
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */,
|
||||
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */,
|
||||
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */,
|
||||
DAADCC4719FAFFAD00987B1D /* NSNotificationCenter+PearlEasyCleanup.h in Headers */,
|
||||
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */,
|
||||
@@ -2185,6 +2288,37 @@
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXLegacyTarget section */
|
||||
DA5B0B611F3D416500B663F0 /* libsodium-osx */ = {
|
||||
isa = PBXLegacyTarget;
|
||||
buildArgumentsString = "$(ACTION)";
|
||||
buildConfigurationList = DA5B0B621F3D416500B663F0 /* Build configuration list for PBXLegacyTarget "libsodium-osx" */;
|
||||
buildPhases = (
|
||||
);
|
||||
buildToolPath = "Scripts/build_libsodium-osx";
|
||||
buildWorkingDirectory = "";
|
||||
dependencies = (
|
||||
);
|
||||
name = "libsodium-osx";
|
||||
passBuildSettingsInEnvironment = 1;
|
||||
productName = "libsodium-osx";
|
||||
};
|
||||
DAB7AE421F3D466D00C856B1 /* libjson-c-osx */ = {
|
||||
isa = PBXLegacyTarget;
|
||||
buildArgumentsString = "$(ACTION)";
|
||||
buildConfigurationList = DAB7AE431F3D466D00C856B1 /* Build configuration list for PBXLegacyTarget "libjson-c-osx" */;
|
||||
buildPhases = (
|
||||
);
|
||||
buildToolPath = "Scripts/build_libjson-c-osx";
|
||||
buildWorkingDirectory = "";
|
||||
dependencies = (
|
||||
);
|
||||
name = "libjson-c-osx";
|
||||
passBuildSettingsInEnvironment = 1;
|
||||
productName = "libjson-c";
|
||||
};
|
||||
/* End PBXLegacyTarget section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DA1C7AA61F1A8F24009A3551 /* mpw-cli */ = {
|
||||
isa = PBXNativeTarget;
|
||||
@@ -2197,6 +2331,8 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DAB7AE581F3D64A600C856B1 /* PBXTargetDependency */,
|
||||
DAB7AE3B1F3D424700C856B1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "mpw-cli";
|
||||
productName = "mpw-test";
|
||||
@@ -2214,6 +2350,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DAB7AE391F3D424200C856B1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "mpw-bench";
|
||||
productName = "mpw-test";
|
||||
@@ -2225,7 +2362,6 @@
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
|
||||
buildPhases = (
|
||||
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */,
|
||||
DA0E86A91E9BED9300F4D60E /* Run Script: libsodium/dist-build/osx.sh */,
|
||||
DA5BFA40147E415C00F98B1E /* Sources */,
|
||||
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
||||
DA5BFA42147E415C00F98B1E /* Resources */,
|
||||
@@ -2236,6 +2372,8 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DAB7AE521F3D649400C856B1 /* PBXTargetDependency */,
|
||||
DAB7AE351F3D423600C856B1 /* PBXTargetDependency */,
|
||||
DABFA072176E3FDF00E83589 /* PBXTargetDependency */,
|
||||
);
|
||||
name = MasterPassword;
|
||||
@@ -2254,6 +2392,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DAB7AE371F3D423D00C856B1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "mpw-test";
|
||||
productName = "mpw-test";
|
||||
@@ -2330,6 +2469,11 @@
|
||||
DA1C7AC61F1A8FD8009A3551 = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
DA5B0B611F3D416500B663F0 = {
|
||||
CreatedOnToolsVersion = 8.3.3;
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
DA5BFA43147E415C00F98B1E = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
ProvisioningStyle = Automatic;
|
||||
@@ -2347,6 +2491,11 @@
|
||||
CreatedOnToolsVersion = 6.0.1;
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
DAB7AE421F3D466D00C856B1 = {
|
||||
CreatedOnToolsVersion = 8.3.3;
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
DAC6326B148680650075AEA5 = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
};
|
||||
@@ -2381,6 +2530,8 @@
|
||||
DA67743A1A474A03004F356A /* mpw-test */,
|
||||
DA1C7AC61F1A8FD8009A3551 /* mpw-bench */,
|
||||
DA1C7AA61F1A8F24009A3551 /* mpw-cli */,
|
||||
DA5B0B611F3D416500B663F0 /* libsodium-osx */,
|
||||
DAB7AE421F3D466D00C856B1 /* libjson-c-osx */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -2468,21 +2619,6 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
DA0E86A91E9BED9300F4D60E /* Run Script: libsodium/dist-build/osx.sh */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script: libsodium/dist-build/osx.sh";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = "/bin/sh -e";
|
||||
shellScript = "cd External/libsodium\nif ! [[ -d libsodium-osx ]]; then\n # Xcode misinterpretes autogen.sh's stderr output as errors so we try to silence it.\n [[ -e configure ]] || { err=$(./autogen.sh 2>&1 >&3); } 3>&1 || { x=$?; echo >&2 \"$err\"; exit $x; }\n./dist-build/osx.sh\nfi\n\n# Xcode incorrectly links the dynamic libraries if they're present instead of linking the .a.\nrm -f libsodium-osx/lib/*.dylib";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2537,6 +2673,7 @@
|
||||
DA1C7AAA1F1A8F24009A3551 /* mpw-marshall.c in Sources */,
|
||||
DA1C7AAB1F1A8F24009A3551 /* mpw-types.c in Sources */,
|
||||
DA5B0B3D1F36467900B663F0 /* base64.c in Sources */,
|
||||
DAAF16661F5CA3240013B8AE /* mpw-cli-util.c in Sources */,
|
||||
DA1C7AAC1F1A8F24009A3551 /* mpw-util.c in Sources */,
|
||||
DA1C7AC31F1A8FBA009A3551 /* mpw-cli.c in Sources */,
|
||||
DA7471A31F2B71AE005F3468 /* mpw-marshall-util.c in Sources */,
|
||||
@@ -2569,6 +2706,7 @@
|
||||
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */,
|
||||
DA2686231EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataClass.m in Sources */,
|
||||
DA2686221EBFD7A40001E37E /* MPSiteQuestionEntity+CoreDataProperties.m in Sources */,
|
||||
DA4571201F572F3200D54152 /* PearlCryptUtils.m in Sources */,
|
||||
DACBFCDF1C59B22E007EF90F /* NSMutableSet+Pearl.m in Sources */,
|
||||
DA2686241EBFD7A40001E37E /* MPStoredSiteEntity+CoreDataProperties.m in Sources */,
|
||||
DA6774311A4746AF004F356A /* mpw-util.c in Sources */,
|
||||
@@ -2654,10 +2792,8 @@
|
||||
DAFE4A2B15039824003ABA7C /* PearlObjectUtils.m in Sources */,
|
||||
DAFE4A2E15039824003ABA7C /* PearlStrings.m in Sources */,
|
||||
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */,
|
||||
DAFE4A3515039824003ABA7C /* PearlCryptUtils.m in Sources */,
|
||||
DA89D4ED1A51EABD00AC64D7 /* Pearl-Cocoa.m in Sources */,
|
||||
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
|
||||
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */,
|
||||
DA8ED895192906920099B726 /* PearlTween.m in Sources */,
|
||||
DA2CA4F118D323D3007798F8 /* NSTimer+PearlBlock.m in Sources */,
|
||||
DA3B8452190FC86F00246EEA /* NSManagedObject+Pearl.m in Sources */,
|
||||
@@ -2677,6 +2813,36 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
DAB7AE351F3D423600C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DA5B0B611F3D416500B663F0 /* libsodium-osx */;
|
||||
targetProxy = DAB7AE341F3D423600C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAB7AE371F3D423D00C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DA5B0B611F3D416500B663F0 /* libsodium-osx */;
|
||||
targetProxy = DAB7AE361F3D423D00C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAB7AE391F3D424200C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DA5B0B611F3D416500B663F0 /* libsodium-osx */;
|
||||
targetProxy = DAB7AE381F3D424200C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAB7AE3B1F3D424700C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DA5B0B611F3D416500B663F0 /* libsodium-osx */;
|
||||
targetProxy = DAB7AE3A1F3D424700C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAB7AE521F3D649400C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DAB7AE421F3D466D00C856B1 /* libjson-c-osx */;
|
||||
targetProxy = DAB7AE511F3D649400C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DAB7AE581F3D64A600C856B1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DAB7AE421F3D466D00C856B1 /* libjson-c-osx */;
|
||||
targetProxy = DAB7AE571F3D64A600C856B1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
DABFA072176E3FDF00E83589 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "MasterPassword-Mac-LoginHelper";
|
||||
@@ -2791,6 +2957,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libsodium/libsodium-osx/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/include\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PATH)";
|
||||
@@ -2828,8 +2996,12 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
OTHER_CFLAGS = "-DHAS_SODIUM=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword.Mac;
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
@@ -2875,18 +3047,17 @@
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"/usr/include//libxml2",
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
};
|
||||
name = Test;
|
||||
@@ -2895,19 +3066,16 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
"-DMPW_JSON=1",
|
||||
"-DMPW_COLOR=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@@ -2917,19 +3085,16 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
"-DMPW_JSON=1",
|
||||
"-DMPW_COLOR=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@@ -2939,19 +3104,16 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
"-DMPW_JSON=1",
|
||||
"-DMPW_COLOR=1",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@@ -2961,19 +3123,13 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@@ -2983,19 +3139,13 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
@@ -3005,24 +3155,77 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DA5B0B631F3D416500B663F0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DA5B0B641F3D416500B663F0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DA5B0B651F3D416500B663F0 /* Test */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DA5BFA6B147E415C00F98B1E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -3097,6 +3300,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libsodium/libsodium-osx/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/include\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PATH)";
|
||||
@@ -3188,6 +3393,8 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libsodium/libsodium-osx/include\"",
|
||||
"\"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/include\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
LD_DYLIB_INSTALL_NAME = "@rpath/$(EXECUTABLE_PATH)";
|
||||
@@ -3225,8 +3432,12 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
OTHER_CFLAGS = "-DHAS_SODIUM=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword.Mac;
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
@@ -3253,8 +3464,12 @@
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
"$(PROJECT_DIR)/External/libjson-c/libjson-c-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
OTHER_CFLAGS = "-DHAS_SODIUM=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword.Mac;
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
@@ -3266,18 +3481,17 @@
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"/usr/include//libxml2",
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
};
|
||||
name = Debug;
|
||||
@@ -3287,18 +3501,17 @@
|
||||
buildSettings = {
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/$(PLATFORM_NAME)/include\"",
|
||||
"/usr/include//libxml2",
|
||||
"$(inherited)",
|
||||
/usr/include/libxml2,
|
||||
/usr/local/include,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
|
||||
/usr/local/lib,
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
|
||||
);
|
||||
OTHER_CFLAGS = (
|
||||
"-DHAS_CPERCIVA=0",
|
||||
"-DHAS_SODIUM=1",
|
||||
"-DMPW_SODIUM=1",
|
||||
"-DMPW_CPERCIVA=0",
|
||||
);
|
||||
};
|
||||
name = Release;
|
||||
@@ -3319,6 +3532,65 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAB7AE441F3D466D00C856B1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
DEBUGGING_SYMBOLS = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAB7AE451F3D466D00C856B1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAB7AE461F3D466D00C856B1 /* Test */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
OTHER_CFLAGS = "";
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Test;
|
||||
};
|
||||
DAC63275148680650075AEA5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -3394,6 +3666,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DA5B0B621F3D416500B663F0 /* Build configuration list for PBXLegacyTarget "libsodium-osx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA5B0B631F3D416500B663F0 /* Debug */,
|
||||
DA5B0B641F3D416500B663F0 /* Release */,
|
||||
DA5B0B651F3D416500B663F0 /* Test */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DA5BFA3E147E415C00F98B1E /* Build configuration list for PBXProject "MasterPassword-macOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@@ -3434,6 +3716,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DAB7AE431F3D466D00C856B1 /* Build configuration list for PBXLegacyTarget "libjson-c-osx" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DAB7AE441F3D466D00C856B1 /* Debug */,
|
||||
DAB7AE451F3D466D00C856B1 /* Release */,
|
||||
DAB7AE461F3D466D00C856B1 /* Test */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Test;
|
||||
};
|
||||
DAC63274148680650075AEA5 /* Build configuration list for PBXNativeTarget "jrswizzle" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0830"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AC61F1A8FD8009A3551"
|
||||
BuildableName = "mpw-bench"
|
||||
BlueprintName = "mpw-bench"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AC61F1A8FD8009A3551"
|
||||
BuildableName = "mpw-bench"
|
||||
BlueprintName = "mpw-bench"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AC61F1A8FD8009A3551"
|
||||
BuildableName = "mpw-bench"
|
||||
BlueprintName = "mpw-bench"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AC61F1A8FD8009A3551"
|
||||
BuildableName = "mpw-bench"
|
||||
BlueprintName = "mpw-bench"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0830"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AA61F1A8F24009A3551"
|
||||
BuildableName = "mpw-cli"
|
||||
BlueprintName = "mpw-cli"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AA61F1A8F24009A3551"
|
||||
BuildableName = "mpw-cli"
|
||||
BlueprintName = "mpw-cli"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AA61F1A8F24009A3551"
|
||||
BuildableName = "mpw-cli"
|
||||
BlueprintName = "mpw-cli"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA1C7AA61F1A8F24009A3551"
|
||||
BuildableName = "mpw-cli"
|
||||
BlueprintName = "mpw-cli"
|
||||
ReferencedContainer = "container:MasterPassword-macOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -11,6 +11,7 @@
|
||||
"2FE140B36B7D26140DC8D5E5C639DC5900EFCF35" : 9223372036854775807,
|
||||
"4DDCFFD91B41F00326AD14553BD66CFD366ABD91" : 9223372036854775807,
|
||||
"3ED8592497DB6A564366943C9AAD5A46341B5076" : 9223372036854775807,
|
||||
"B38C14663FCFBB7024902D2DB1D013964189DC3B" : 9223372036854775807,
|
||||
"81A28796384A028E6C2D47C039DB8B3E5DD6D0FC" : 9223372036854775807,
|
||||
"F788B28042EDBEF29EFE34687DA79A778C2CC260" : 0
|
||||
},
|
||||
@@ -23,6 +24,7 @@
|
||||
"2FE140B36B7D26140DC8D5E5C639DC5900EFCF35" : "MasterPassword\/platform-darwin\/External\/uicolor-utilities\/",
|
||||
"4DDCFFD91B41F00326AD14553BD66CFD366ABD91" : "MasterPassword\/platform-darwin\/External\/Pearl\/",
|
||||
"3ED8592497DB6A564366943C9AAD5A46341B5076" : "MasterPassword\/platform-darwin\/External\/AttributedMarkdown\/",
|
||||
"B38C14663FCFBB7024902D2DB1D013964189DC3B" : "MasterPassword\/platform-darwin\/External\/libjson-c\/",
|
||||
"81A28796384A028E6C2D47C039DB8B3E5DD6D0FC" : "MasterPassword\/platform-darwin\/External\/libsodium\/",
|
||||
"F788B28042EDBEF29EFE34687DA79A778C2CC260" : "MasterPassword\/"
|
||||
},
|
||||
@@ -70,6 +72,11 @@
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8A15A8EA0B3D0B497C4883425BC74DF995224BB3"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/json-c\/json-c.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "B38C14663FCFBB7024902D2DB1D013964189DC3B"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:Lyndir\/MasterPassword.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
|
||||
86
platform-darwin/Scripts/build_libjson-c-ios
Executable file
86
platform-darwin/Scripts/build_libjson-c-ios
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE%/*}/../External/libjson-c"
|
||||
[[ -e "${prefix=$PWD/libjson-c-ios}/lib/libjson-c.a" ]] && exit
|
||||
|
||||
# Prepare
|
||||
autoreconf -Iautoconf-archive/m4 --verbose --install --symlink 2>&1 | sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /'
|
||||
rm -rf "${prefix=$PWD/libjson-c-ios}"
|
||||
mkdir -p "$prefix/lib" \
|
||||
"${prefix_i386=$prefix/tmp/i386}" \
|
||||
"${prefix_x86_64=$prefix/tmp/x86_64}" \
|
||||
"${prefix_armv7=$prefix/tmp/armv7}" \
|
||||
"${prefix_armv7s=$prefix/tmp/armv7s}" \
|
||||
"${prefix_arm64=$prefix/tmp/arm64}"
|
||||
|
||||
# Targets
|
||||
(
|
||||
## ARCH: i386
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphonesimulator)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphonesimulator)/usr/bin:$PATH"
|
||||
export CFLAGS="-arch i386 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g $CFLAGS"
|
||||
export LDFLAGS="-arch i386 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s clean
|
||||
./configure --host=i686-apple --disable-shared --prefix="$prefix_i386"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: x86_64
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphonesimulator)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphonesimulator)/usr/bin:$PATH"
|
||||
export CFLAGS="-arch x86_64 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g $CFLAGS"
|
||||
export LDFLAGS="-arch x86_64 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s clean
|
||||
./configure --host=x86_64-apple --disable-shared --prefix="$prefix_x86_64"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: armv7
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphoneos)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphoneos)/usr/bin:$PATH"
|
||||
export CFLAGS="-mthumb -arch armv7 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g $CFLAGS"
|
||||
export LDFLAGS="-mthumb -arch armv7 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s clean
|
||||
./configure --host=x86_64-apple --target=arm-apple --disable-shared --prefix="$prefix_armv7"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: armv7s
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphoneos)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphoneos)/usr/bin:$PATH"
|
||||
export CFLAGS="-mthumb -arch armv7s -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g $CFLAGS"
|
||||
export LDFLAGS="-mthumb -arch armv7s -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s clean
|
||||
./configure --host=x86_64-apple --target=arm-apple --disable-shared --prefix="$prefix_armv7s"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: arm64
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphoneos)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphoneos)/usr/bin:$PATH"
|
||||
export CFLAGS="-mthumb -arch arm64 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g $CFLAGS"
|
||||
export LDFLAGS="-mthumb -arch arm64 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s clean
|
||||
./configure --host=x86_64-apple --target=arm-apple --disable-shared --prefix="$prefix_arm64"
|
||||
make -j3 install
|
||||
)
|
||||
|
||||
# Merge Binaries
|
||||
mv -f -- "$prefix_arm64/include" "$prefix/"
|
||||
lipo -create \
|
||||
"$prefix_i386/lib/libjson-c.a" \
|
||||
"$prefix_x86_64/lib/libjson-c.a" \
|
||||
"$prefix_armv7/lib/libjson-c.a" \
|
||||
"$prefix_armv7s/lib/libjson-c.a" \
|
||||
"$prefix_arm64/lib/libjson-c.a" \
|
||||
-output "$prefix/lib/libjson-c.a"
|
||||
|
||||
# Cleanup
|
||||
rm -rf -- "$prefix/tmp"
|
||||
make -s really-clean
|
||||
27
platform-darwin/Scripts/build_libjson-c-osx
Executable file
27
platform-darwin/Scripts/build_libjson-c-osx
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE%/*}/../External/libjson-c"
|
||||
[[ -e "${prefix=$PWD/libjson-c-osx}/lib/libjson-c.a" ]] && exit
|
||||
|
||||
# Prepare
|
||||
autoreconf -Iautoconf-archive/m4 --verbose --install --symlink 2>&1 | sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /'
|
||||
rm -rf "${prefix=$PWD/libjson-c-osx}"
|
||||
mkdir -p "$prefix"
|
||||
|
||||
# Targets
|
||||
(
|
||||
## ARCH: x86_64
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk macosx)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk macosx)/usr/bin:$PATH"
|
||||
export CFLAGS="-arch x86_64 -isysroot $SDKROOT -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET:-10.8} -O2 -g $CFLAGS" # -flto
|
||||
export LDFLAGS="-arch x86_64 -isysroot $SDKROOT -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET:-10.8} $LDFLAGS" # -flto
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s clean
|
||||
./configure --disable-shared --prefix="$prefix"
|
||||
make -j3 check
|
||||
make -j3 install
|
||||
)
|
||||
|
||||
# Cleanup
|
||||
make -s really-clean
|
||||
86
platform-darwin/Scripts/build_libsodium-ios
Executable file
86
platform-darwin/Scripts/build_libsodium-ios
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE%/*}/../External/libsodium"
|
||||
[[ -e "${prefix=$PWD/libsodium-ios}/lib/libsodium.a" ]] && exit
|
||||
|
||||
# Prepare
|
||||
autoreconf --verbose --install --symlink 2>&1 | sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /'
|
||||
rm -rf "${prefix=$PWD/libsodium-ios}"
|
||||
mkdir -p "$prefix/lib" \
|
||||
"${prefix_i386=$prefix/tmp/i386}" \
|
||||
"${prefix_x86_64=$prefix/tmp/x86_64}" \
|
||||
"${prefix_armv7=$prefix/tmp/armv7}" \
|
||||
"${prefix_armv7s=$prefix/tmp/armv7s}" \
|
||||
"${prefix_arm64=$prefix/tmp/arm64}"
|
||||
|
||||
# Targets
|
||||
(
|
||||
## ARCH: i386
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphonesimulator)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphonesimulator)/usr/bin:$PATH"
|
||||
export CFLAGS="-arch i386 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g -flto $CFLAGS"
|
||||
export LDFLAGS="-arch i386 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -flto $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s distclean
|
||||
./configure --host=i686-apple --disable-shared --prefix="$prefix_i386"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: x86_64
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphonesimulator)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphonesimulator)/usr/bin:$PATH"
|
||||
export CFLAGS="-arch x86_64 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g -flto $CFLAGS"
|
||||
export LDFLAGS="-arch x86_64 -isysroot $SDKROOT -mios-simulator-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -flto $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s distclean
|
||||
./configure --host=x86_64-apple --disable-shared --prefix="$prefix_x86_64"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: armv7
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphoneos)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphoneos)/usr/bin:$PATH"
|
||||
export CFLAGS="-mthumb -arch armv7 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g -flto $CFLAGS"
|
||||
export LDFLAGS="-mthumb -arch armv7 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -flto $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s distclean
|
||||
./configure --host=x86_64-apple --target=arm-apple --disable-shared --prefix="$prefix_armv7"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: armv7s
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphoneos)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphoneos)/usr/bin:$PATH"
|
||||
export CFLAGS="-mthumb -arch armv7s -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g -flto $CFLAGS"
|
||||
export LDFLAGS="-mthumb -arch armv7s -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -flto $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s distclean
|
||||
./configure --host=x86_64-apple --target=arm-apple --disable-shared --prefix="$prefix_armv7s"
|
||||
make -j3 install
|
||||
)
|
||||
(
|
||||
## ARCH: arm64
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk iphoneos)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk iphoneos)/usr/bin:$PATH"
|
||||
export CFLAGS="-mthumb -arch arm64 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -O2 -g -flto $CFLAGS"
|
||||
export LDFLAGS="-mthumb -arch arm64 -isysroot $SDKROOT -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET:-8.0} -flto $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s distclean
|
||||
./configure --host=x86_64-apple --target=arm-apple --disable-shared --prefix="$prefix_arm64"
|
||||
make -j3 install
|
||||
)
|
||||
|
||||
# Merge Binaries
|
||||
mv -f -- "$prefix_arm64/include" "$prefix/"
|
||||
lipo -create \
|
||||
"$prefix_i386/lib/libsodium.a" \
|
||||
"$prefix_x86_64/lib/libsodium.a" \
|
||||
"$prefix_armv7/lib/libsodium.a" \
|
||||
"$prefix_armv7s/lib/libsodium.a" \
|
||||
"$prefix_arm64/lib/libsodium.a" \
|
||||
-output "$prefix/lib/libsodium.a"
|
||||
|
||||
# Cleanup
|
||||
rm -rf -- "$prefix/tmp"
|
||||
make -s distclean
|
||||
28
platform-darwin/Scripts/build_libsodium-osx
Executable file
28
platform-darwin/Scripts/build_libsodium-osx
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE%/*}/../External/libsodium"
|
||||
[[ -e "${prefix=$PWD/libsodium-osx}/lib/libsodium.a" ]] && exit
|
||||
|
||||
# Inspired by libsodium/dist-build/osx.sh
|
||||
# Prepare
|
||||
autoreconf --verbose --install --symlink 2>&1 | sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /'
|
||||
rm -rf "${prefix=$PWD/libsodium-osx}"
|
||||
mkdir -p "$prefix"
|
||||
|
||||
# Targets
|
||||
(
|
||||
## ARCH: x86_64
|
||||
export SDKROOT="$(xcrun --show-sdk-path --sdk macosx)"
|
||||
export PATH="$(xcrun --show-sdk-platform-path --sdk macosx)/usr/bin:$PATH"
|
||||
export CFLAGS="-arch x86_64 -isysroot $SDKROOT -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET:-10.8} -O2 -g -flto $CFLAGS"
|
||||
export LDFLAGS="-arch x86_64 -isysroot $SDKROOT -mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET:-10.8} -flto $LDFLAGS"
|
||||
export CPPFLAGS="$CFLAGS $CPPFLAGS"
|
||||
[[ -e Makefile ]] && make -s distclean
|
||||
./configure --disable-shared --prefix="$prefix"
|
||||
make -j3 check
|
||||
make -j3 install
|
||||
)
|
||||
|
||||
# Cleanup
|
||||
make -s distclean
|
||||
@@ -52,49 +52,44 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
||||
- (NSData *)keyIDForKey:(MPMasterKey)masterKey;
|
||||
- (NSData *)keyDataForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword;
|
||||
|
||||
- (NSString *)nameOfType:(MPSiteType)type;
|
||||
- (NSString *)shortNameOfType:(MPSiteType)type;
|
||||
- (NSString *)classNameOfType:(MPSiteType)type;
|
||||
- (Class)classOfType:(MPSiteType)type;
|
||||
- (NSString *)nameOfType:(MPResultType)type;
|
||||
- (NSString *)shortNameOfType:(MPResultType)type;
|
||||
- (NSString *)classNameOfType:(MPResultType)type;
|
||||
- (Class)classOfType:(MPResultType)type;
|
||||
- (NSArray *)allTypes;
|
||||
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType;
|
||||
- (MPSiteType)defaultType;
|
||||
- (MPSiteType)nextType:(MPSiteType)type;
|
||||
- (MPSiteType)previousType:(MPSiteType)type;
|
||||
- (NSArray *)allTypesStartingWith:(MPResultType)startingType;
|
||||
- (MPResultType)defaultType;
|
||||
- (MPResultType)nextType:(MPResultType)type;
|
||||
- (MPResultType)previousType:(MPResultType)type;
|
||||
|
||||
- (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key;
|
||||
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
usingKey:(MPKey *)key;
|
||||
- (NSString *)generateAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key;
|
||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key;
|
||||
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key;
|
||||
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
|
||||
withCounter:(MPCounterValue)counter usingKey:(MPKey *)key;
|
||||
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key;
|
||||
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
|
||||
withCounter:(MPCounterValue)counter variant:(MPKeyPurpose)purpose context:(NSString *)context usingKey:(MPKey *)key;
|
||||
|
||||
- (NSString *)storedLoginForSite:(MPStoredSiteEntity *)site usingKey:(MPKey *)key;
|
||||
- (NSString *)storedPasswordForSite:(MPStoredSiteEntity *)site usingKey:(MPKey *)key;
|
||||
- (BOOL)savePassword:(NSString *)clearPassword toSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||
|
||||
- (BOOL)savePassword:(NSString *)clearPassword toSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
|
||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||
- (NSString *)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||
- (NSString *)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)key;
|
||||
|
||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
|
||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
|
||||
- (NSString *)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
|
||||
- (NSString *)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)siteKey;
|
||||
|
||||
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey
|
||||
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key
|
||||
result:(void ( ^ )(NSString *result))resultBlock;
|
||||
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey
|
||||
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)key
|
||||
result:(void ( ^ )(NSString *result))resultBlock;
|
||||
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey
|
||||
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key
|
||||
result:(void ( ^ )(NSString *result))resultBlock;
|
||||
- (void)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)siteKey
|
||||
- (void)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)key
|
||||
result:(void ( ^ )(NSString *result))resultBlock;
|
||||
|
||||
- (void)importProtectedPassword:(NSString *)protectedPassword protectedByKey:(MPKey *)importKey
|
||||
intoSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
|
||||
- (void)importClearTextPassword:(NSString *)clearPassword intoSite:(MPSiteEntity *)site
|
||||
usingKey:(MPKey *)siteKey;
|
||||
- (NSString *)exportPasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey;
|
||||
- (void)importPassword:(NSString *)protectedPassword protectedByKey:(MPKey *)importKey
|
||||
intoSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||
- (NSString *)exportPasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)key;
|
||||
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPSiteType)type byAttacker:(MPAttacker)attacker;
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPResultType)type byAttacker:(MPAttacker)attacker;
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordString:(NSString *)password byAttacker:(MPAttacker)attacker;
|
||||
|
||||
@end
|
||||
|
||||
@@ -133,7 +133,7 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
keyData = [NSData dataWithBytes:masterKey length:MPMasterKeySize];
|
||||
trc( @"User: %@, password: %@ derives to key ID: %@ (took %0.2fs)", //
|
||||
fullName, masterPassword, [self keyIDForKey:masterKey], -[start timeIntervalSinceNow] );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
mpw_free( &masterKey, MPMasterKeySize );
|
||||
}
|
||||
}];
|
||||
|
||||
@@ -145,126 +145,135 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
return [[NSData dataWithBytesNoCopy:(void *)masterKey length:MPMasterKeySize] hashWith:PearlHashSHA256];
|
||||
}
|
||||
|
||||
- (NSString *)nameOfType:(MPSiteType)type {
|
||||
- (NSString *)nameOfType:(MPResultType)type {
|
||||
|
||||
if (!type)
|
||||
return nil;
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPResultTypeTemplateMaximum:
|
||||
return @"Maximum Security Password";
|
||||
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPResultTypeTemplateLong:
|
||||
return @"Long Password";
|
||||
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPResultTypeTemplateMedium:
|
||||
return @"Medium Password";
|
||||
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPResultTypeTemplateBasic:
|
||||
return @"Basic Password";
|
||||
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPResultTypeTemplateShort:
|
||||
return @"Short Password";
|
||||
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPResultTypeTemplatePIN:
|
||||
return @"PIN";
|
||||
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPResultTypeTemplateName:
|
||||
return @"Name";
|
||||
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
case MPResultTypeTemplatePhrase:
|
||||
return @"Phrase";
|
||||
|
||||
case MPSiteTypeStoredPersonal:
|
||||
case MPResultTypeStatefulPersonal:
|
||||
return @"Personal Password";
|
||||
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
case MPResultTypeStatefulDevice:
|
||||
return @"Device Private Password";
|
||||
|
||||
case MPResultTypeDeriveKey:
|
||||
return @"Crypto Key";
|
||||
}
|
||||
|
||||
Throw( @"Type not supported: %lu", (long)type );
|
||||
}
|
||||
|
||||
- (NSString *)shortNameOfType:(MPSiteType)type {
|
||||
- (NSString *)shortNameOfType:(MPResultType)type {
|
||||
|
||||
if (!type)
|
||||
return nil;
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPResultTypeTemplateMaximum:
|
||||
return @"Maximum";
|
||||
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPResultTypeTemplateLong:
|
||||
return @"Long";
|
||||
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPResultTypeTemplateMedium:
|
||||
return @"Medium";
|
||||
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPResultTypeTemplateBasic:
|
||||
return @"Basic";
|
||||
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPResultTypeTemplateShort:
|
||||
return @"Short";
|
||||
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPResultTypeTemplatePIN:
|
||||
return @"PIN";
|
||||
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPResultTypeTemplateName:
|
||||
return @"Name";
|
||||
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
case MPResultTypeTemplatePhrase:
|
||||
return @"Phrase";
|
||||
|
||||
case MPSiteTypeStoredPersonal:
|
||||
case MPResultTypeStatefulPersonal:
|
||||
return @"Personal";
|
||||
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
case MPResultTypeStatefulDevice:
|
||||
return @"Device";
|
||||
|
||||
case MPResultTypeDeriveKey:
|
||||
return @"Key";
|
||||
}
|
||||
|
||||
Throw( @"Type not supported: %lu", (long)type );
|
||||
}
|
||||
|
||||
- (NSString *)classNameOfType:(MPSiteType)type {
|
||||
- (NSString *)classNameOfType:(MPResultType)type {
|
||||
|
||||
return NSStringFromClass( [self classOfType:type] );
|
||||
}
|
||||
|
||||
- (Class)classOfType:(MPSiteType)type {
|
||||
- (Class)classOfType:(MPResultType)type {
|
||||
|
||||
if (!type)
|
||||
Throw( @"No type given." );
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPResultTypeTemplateMaximum:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPResultTypeTemplateLong:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPResultTypeTemplateMedium:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPResultTypeTemplateBasic:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPResultTypeTemplateShort:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPResultTypeTemplatePIN:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPResultTypeTemplateName:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
case MPResultTypeTemplatePhrase:
|
||||
return [MPGeneratedSiteEntity class];
|
||||
|
||||
case MPSiteTypeStoredPersonal:
|
||||
case MPResultTypeStatefulPersonal:
|
||||
return [MPStoredSiteEntity class];
|
||||
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
case MPResultTypeStatefulDevice:
|
||||
return [MPStoredSiteEntity class];
|
||||
|
||||
case MPResultTypeDeriveKey:
|
||||
break;
|
||||
}
|
||||
|
||||
Throw( @"Type not supported: %lu", (long)type );
|
||||
@@ -272,13 +281,13 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
|
||||
- (NSArray *)allTypes {
|
||||
|
||||
return [self allTypesStartingWith:MPSiteTypeGeneratedPhrase];
|
||||
return [self allTypesStartingWith:MPResultTypeTemplatePhrase];
|
||||
}
|
||||
|
||||
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType {
|
||||
- (NSArray *)allTypesStartingWith:(MPResultType)startingType {
|
||||
|
||||
NSMutableArray *allTypes = [[NSMutableArray alloc] initWithCapacity:8];
|
||||
MPSiteType currentType = startingType;
|
||||
MPResultType currentType = startingType;
|
||||
do {
|
||||
[allTypes addObject:@(currentType)];
|
||||
} while ((currentType = [self nextType:currentType]) != startingType);
|
||||
@@ -286,199 +295,173 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
return allTypes;
|
||||
}
|
||||
|
||||
- (MPSiteType)defaultType {
|
||||
- (MPResultType)defaultType {
|
||||
|
||||
return MPSiteTypeGeneratedLong;
|
||||
return MPResultTypeTemplateLong;
|
||||
}
|
||||
|
||||
- (MPSiteType)nextType:(MPSiteType)type {
|
||||
- (MPResultType)nextType:(MPResultType)type {
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
return MPSiteTypeGeneratedName;
|
||||
case MPSiteTypeGeneratedName:
|
||||
return MPSiteTypeGeneratedMaximum;
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
return MPSiteTypeGeneratedLong;
|
||||
case MPSiteTypeGeneratedLong:
|
||||
return MPSiteTypeGeneratedMedium;
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
return MPSiteTypeGeneratedBasic;
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
return MPSiteTypeGeneratedShort;
|
||||
case MPSiteTypeGeneratedShort:
|
||||
return MPSiteTypeGeneratedPIN;
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
return MPSiteTypeStoredPersonal;
|
||||
case MPSiteTypeStoredPersonal:
|
||||
return MPSiteTypeStoredDevicePrivate;
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
return MPSiteTypeGeneratedPhrase;
|
||||
case MPResultTypeTemplatePhrase:
|
||||
return MPResultTypeTemplateName;
|
||||
case MPResultTypeTemplateName:
|
||||
return MPResultTypeTemplateMaximum;
|
||||
case MPResultTypeTemplateMaximum:
|
||||
return MPResultTypeTemplateLong;
|
||||
case MPResultTypeTemplateLong:
|
||||
return MPResultTypeTemplateMedium;
|
||||
case MPResultTypeTemplateMedium:
|
||||
return MPResultTypeTemplateBasic;
|
||||
case MPResultTypeTemplateBasic:
|
||||
return MPResultTypeTemplateShort;
|
||||
case MPResultTypeTemplateShort:
|
||||
return MPResultTypeTemplatePIN;
|
||||
case MPResultTypeTemplatePIN:
|
||||
return MPResultTypeStatefulPersonal;
|
||||
case MPResultTypeStatefulPersonal:
|
||||
return MPResultTypeStatefulDevice;
|
||||
case MPResultTypeStatefulDevice:
|
||||
return MPResultTypeTemplatePhrase;
|
||||
case MPResultTypeDeriveKey:
|
||||
break;
|
||||
}
|
||||
|
||||
return [self defaultType];
|
||||
}
|
||||
|
||||
- (MPSiteType)previousType:(MPSiteType)type {
|
||||
- (MPResultType)previousType:(MPResultType)type {
|
||||
|
||||
MPSiteType previousType = type, nextType = type;
|
||||
MPResultType previousType = type, nextType = type;
|
||||
while ((nextType = [self nextType:nextType]) != type)
|
||||
previousType = nextType;
|
||||
|
||||
return previousType;
|
||||
}
|
||||
|
||||
- (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
|
||||
- (NSString *)mpwLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
|
||||
|
||||
return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedName withCounter:1
|
||||
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplateName parameter:nil withCounter:MPCounterValueInitial
|
||||
variant:MPKeyPurposeIdentification context:nil usingKey:key];
|
||||
}
|
||||
|
||||
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
usingKey:(MPKey *)key {
|
||||
- (NSString *)mpwTemplateForSiteNamed:(NSString *)name ofType:(MPResultType)type
|
||||
withCounter:(MPCounterValue)counter usingKey:(MPKey *)key {
|
||||
|
||||
return [self generateContentForSiteNamed:name ofType:type withCounter:counter
|
||||
return [self mpwResultForSiteNamed:name ofType:type parameter:nil withCounter:counter
|
||||
variant:MPKeyPurposeAuthentication context:nil usingKey:key];
|
||||
}
|
||||
|
||||
- (NSString *)generateAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key {
|
||||
- (NSString *)mpwAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key {
|
||||
|
||||
return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedPhrase withCounter:1
|
||||
return [self mpwResultForSiteNamed:name ofType:MPResultTypeTemplatePhrase parameter:nil withCounter:MPCounterValueInitial
|
||||
variant:MPKeyPurposeRecovery context:question usingKey:key];
|
||||
}
|
||||
|
||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key {
|
||||
- (NSString *)mpwResultForSiteNamed:(NSString *)name ofType:(MPResultType)type parameter:(NSString *)parameter
|
||||
withCounter:(MPCounterValue)counter variant:(MPKeyPurpose)purpose context:(NSString *)context
|
||||
usingKey:(MPKey *)key {
|
||||
|
||||
__block NSString *content = nil;
|
||||
__block NSString *result = nil;
|
||||
[self mpw_perform:^{
|
||||
char const *contentBytes = mpw_passwordForSite( [key keyForAlgorithm:self],
|
||||
name.UTF8String, type, (uint32_t)counter, variant, context.UTF8String, [self version] );
|
||||
if (contentBytes) {
|
||||
content = [NSString stringWithCString:contentBytes encoding:NSUTF8StringEncoding];
|
||||
mpw_free_string( contentBytes );
|
||||
char const *resultBytes = mpw_siteResult( [key keyForAlgorithm:self],
|
||||
name.UTF8String, counter, purpose, context.UTF8String, type, parameter.UTF8String, [self version] );
|
||||
if (resultBytes) {
|
||||
result = [NSString stringWithCString:resultBytes encoding:NSUTF8StringEncoding];
|
||||
mpw_free_string( &resultBytes );
|
||||
}
|
||||
}];
|
||||
|
||||
return content;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString *)storedLoginForSite:(MPStoredSiteEntity *)site usingKey:(MPKey *)key {
|
||||
- (BOOL)savePassword:(NSString *)plainText toSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)storedPasswordForSite:(MPStoredSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
return [self decryptContent:site.contentObject usingKey:key];
|
||||
}
|
||||
|
||||
- (BOOL)savePassword:(NSString *)clearContent toSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
switch (site.type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPSiteTypeGeneratedPhrase: {
|
||||
wrn( @"Cannot save content to site with generated type %lu.", (long)site.type );
|
||||
if (!(site.type & MPResultTypeClassStateful)) {
|
||||
wrn( @"Can only save content to site with a stateful type: %lu.", (long)site.type );
|
||||
return NO;
|
||||
}
|
||||
|
||||
case MPSiteTypeStoredPersonal: {
|
||||
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
if (![site isKindOfClass:[MPStoredSiteEntity class]]) {
|
||||
wrn( @"Site with stored type %lu is not an MPStoredSiteEntity, but a %@.",
|
||||
(long)site.type, [site class] );
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSData *encryptionKey = [siteKey keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:encryptionKey padding:YES];
|
||||
if ([((MPStoredSiteEntity *)site).contentObject isEqualToData:encryptedContent])
|
||||
return NO;
|
||||
|
||||
((MPStoredSiteEntity *)site).contentObject = encryptedContent;
|
||||
return YES;
|
||||
}
|
||||
case MPSiteTypeStoredDevicePrivate: {
|
||||
if (![site isKindOfClass:[MPStoredSiteEntity class]]) {
|
||||
wrn( @"Site with stored type %lu is not an MPStoredSiteEntity, but a %@.",
|
||||
(long)site.type, [site class] );
|
||||
return NO;
|
||||
__block NSData *state = nil;
|
||||
if (plainText)
|
||||
[self mpw_perform:^{
|
||||
char const *stateBytes = mpw_siteState( [key keyForAlgorithm:self], site.name.UTF8String,
|
||||
MPCounterValueInitial, MPKeyPurposeAuthentication, NULL, site.type, plainText.UTF8String, [self version] );
|
||||
if (stateBytes) {
|
||||
state = [[NSString stringWithCString:stateBytes encoding:NSUTF8StringEncoding] decodeBase64];
|
||||
mpw_free_string( &stateBytes );
|
||||
}
|
||||
}];
|
||||
|
||||
NSData *encryptionKey = [siteKey keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:encryptionKey padding:YES];
|
||||
NSDictionary *siteQuery = [self queryForDevicePrivateSiteNamed:site.name];
|
||||
if (!encryptedContent)
|
||||
NSDictionary *siteQuery = [self queryForSite:site];
|
||||
if (!state)
|
||||
[PearlKeyChain deleteItemForQuery:siteQuery];
|
||||
else
|
||||
[PearlKeyChain addOrUpdateItemForQuery:siteQuery withAttributes:@{
|
||||
(__bridge id)kSecValueData : encryptedContent,
|
||||
(__bridge id)kSecValueData: state,
|
||||
#if TARGET_OS_IPHONE
|
||||
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
|
||||
(__bridge id)kSecAttrAccessible:
|
||||
site.type & MPSiteFeatureDevicePrivate? (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
||||
: (__bridge id)kSecAttrAccessibleWhenUnlocked,
|
||||
#endif
|
||||
}];
|
||||
((MPStoredSiteEntity *)site).contentObject = nil;
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
Throw( @"Unsupported type: %ld", (long)site.type );
|
||||
}
|
||||
|
||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolveLoginForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
[self resolveLoginForSite:site usingKey:key result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolvePasswordForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
[self resolvePasswordForSite:site usingKey:key result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (NSString *)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
- (NSString *)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolveAnswerForSite:site usingKey:siteKey result:^(NSString *result_) {
|
||||
[self resolveAnswerForSite:site usingKey:key result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (NSString *)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)siteKey {
|
||||
- (NSString *)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)key {
|
||||
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[self resolveAnswerForQuestion:question usingKey:siteKey result:^(NSString *result_) {
|
||||
[self resolveAnswerForQuestion:question usingKey:key result:^(NSString *result_) {
|
||||
setResult( result_ );
|
||||
}];
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
|
||||
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key result:(void ( ^ )(NSString *result))resultBlock {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
NSString *name = site.name;
|
||||
BOOL loginGenerated = site.loginGenerated && [[MPAppDelegate_Shared get] isFeatureUnlocked:MPProductGenerateLogins];
|
||||
NSString *loginName = site.loginName;
|
||||
id<MPAlgorithm> algorithm = nil;
|
||||
if (!name.length)
|
||||
err( @"Missing name." );
|
||||
else if (!siteKey)
|
||||
else if (!key)
|
||||
err( @"Missing key." );
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
@@ -487,244 +470,144 @@ static NSOperationQueue *_mpwQueue = nil;
|
||||
resultBlock( loginName );
|
||||
else
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateLoginForSiteNamed:name usingKey:siteKey] );
|
||||
resultBlock( [algorithm mpwLoginForSiteNamed:name usingKey:key] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
|
||||
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)key result:(void ( ^ )(NSString *result))resultBlock {
|
||||
|
||||
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
NSString *name = site.name;
|
||||
MPResultType type = site.type;
|
||||
id<MPAlgorithm> algorithm = nil;
|
||||
if (!site.name.length)
|
||||
err( @"Missing name." );
|
||||
else if (!key)
|
||||
err( @"Missing key." );
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
switch (site.type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPSiteTypeGeneratedPhrase: {
|
||||
case MPResultTypeTemplateMaximum:
|
||||
case MPResultTypeTemplateLong:
|
||||
case MPResultTypeTemplateMedium:
|
||||
case MPResultTypeTemplateBasic:
|
||||
case MPResultTypeTemplateShort:
|
||||
case MPResultTypeTemplatePIN:
|
||||
case MPResultTypeTemplateName:
|
||||
case MPResultTypeTemplatePhrase: {
|
||||
if (![site isKindOfClass:[MPGeneratedSiteEntity class]]) {
|
||||
wrn( @"Site with generated type %lu is not an MPGeneratedSiteEntity, but a %@.",
|
||||
(long)site.type, [site class] );
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *name = site.name;
|
||||
MPSiteType type = site.type;
|
||||
NSUInteger counter = ((MPGeneratedSiteEntity *)site).counter;
|
||||
id<MPAlgorithm> algorithm = nil;
|
||||
if (!site.name.length)
|
||||
err( @"Missing name." );
|
||||
else if (!siteKey)
|
||||
err( @"Missing key." );
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
MPCounterValue counter = ((MPGeneratedSiteEntity *)site).counter;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generatePasswordForSiteNamed:name ofType:type withCounter:counter usingKey:siteKey] );
|
||||
resultBlock( [algorithm mpwTemplateForSiteNamed:name ofType:type withCounter:counter usingKey:key] );
|
||||
} );
|
||||
break;
|
||||
}
|
||||
|
||||
case MPSiteTypeStoredPersonal: {
|
||||
case MPResultTypeStatefulPersonal:
|
||||
case MPResultTypeStatefulDevice: {
|
||||
if (![site isKindOfClass:[MPStoredSiteEntity class]]) {
|
||||
wrn( @"Site with stored type %lu is not an MPStoredSiteEntity, but a %@.",
|
||||
(long)site.type, [site class] );
|
||||
break;
|
||||
}
|
||||
|
||||
NSData *encryptedContent = ((MPStoredSiteEntity *)site).contentObject;
|
||||
NSDictionary *siteQuery = [self queryForSite:site];
|
||||
NSData *state = [PearlKeyChain dataOfItemForQuery:siteQuery];
|
||||
state = state?: ((MPStoredSiteEntity *)site).contentObject;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [self decryptContent:encryptedContent usingKey:siteKey] );
|
||||
resultBlock( [algorithm mpwResultForSiteNamed:name ofType:type parameter:[state encodeBase64]
|
||||
withCounter:MPCounterValueInitial variant:MPKeyPurposeAuthentication context:nil
|
||||
usingKey:key] );
|
||||
} );
|
||||
break;
|
||||
}
|
||||
case MPSiteTypeStoredDevicePrivate: {
|
||||
NSAssert( [site isKindOfClass:[MPStoredSiteEntity class]],
|
||||
@"Site with stored type %lu is not an MPStoredSiteEntity, but a %@.", (long)site.type,
|
||||
[site class] );
|
||||
|
||||
NSDictionary *siteQuery = [self queryForDevicePrivateSiteNamed:site.name];
|
||||
NSData *encryptedContent = [PearlKeyChain dataOfItemForQuery:siteQuery];
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [self decryptContent:encryptedContent usingKey:siteKey] );
|
||||
} );
|
||||
case MPResultTypeDeriveKey:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Throw( @"Type not supported: %lu", (long)type );
|
||||
}
|
||||
|
||||
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
|
||||
- (void)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)key result:(void ( ^ )(NSString *result))resultBlock {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
NSString *name = site.name;
|
||||
id<MPAlgorithm> algorithm = nil;
|
||||
if (!site.name.length)
|
||||
err( @"Missing name." );
|
||||
else if (!siteKey)
|
||||
else if (!key)
|
||||
err( @"Missing key." );
|
||||
else
|
||||
algorithm = site.algorithm;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateAnswerForSiteNamed:name onQuestion:nil usingKey:siteKey] );
|
||||
resultBlock( [algorithm mpwAnswerForSiteNamed:name onQuestion:nil usingKey:key] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)siteKey
|
||||
- (void)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)key
|
||||
result:(void ( ^ )(NSString *result))resultBlock {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:question.site.user.algorithm] isEqualToData:question.site.user.keyID],
|
||||
NSAssert( [[key keyIDForAlgorithm:question.site.user.algorithm] isEqualToData:question.site.user.keyID],
|
||||
@"Site does not belong to current user." );
|
||||
NSString *name = question.site.name;
|
||||
NSString *keyword = question.keyword;
|
||||
id<MPAlgorithm> algorithm = nil;
|
||||
if (!name.length)
|
||||
err( @"Missing name." );
|
||||
else if (!siteKey)
|
||||
else if (!key)
|
||||
err( @"Missing key." );
|
||||
else if ([[MPAppDelegate_Shared get] isFeatureUnlocked:MPProductGenerateAnswers])
|
||||
algorithm = question.site.algorithm;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateAnswerForSiteNamed:name onQuestion:keyword usingKey:siteKey] );
|
||||
resultBlock( [algorithm mpwAnswerForSiteNamed:name onQuestion:keyword usingKey:key] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)importProtectedPassword:(NSString *)protectedContent protectedByKey:(MPKey *)importKey
|
||||
intoSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
- (void)importPassword:(NSString *)cipherText protectedByKey:(MPKey *)importKey
|
||||
intoSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
switch (site.type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
break;
|
||||
|
||||
case MPSiteTypeStoredPersonal: {
|
||||
if (![site isKindOfClass:[MPStoredSiteEntity class]]) {
|
||||
wrn( @"Site with stored type %lu is not an MPStoredSiteEntity, but a %@.",
|
||||
(long)site.type, [site class] );
|
||||
break;
|
||||
}
|
||||
if ([[importKey keyIDForAlgorithm:self] isEqualToData:[siteKey keyIDForAlgorithm:self]])
|
||||
((MPStoredSiteEntity *)site).contentObject = [protectedContent decodeBase64];
|
||||
|
||||
else {
|
||||
NSString *clearContent = [self decryptContent:[protectedContent decodeBase64] usingKey:importKey];
|
||||
[self importClearTextPassword:clearContent intoSite:site usingKey:siteKey];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
break;
|
||||
NSAssert( [[key keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
if (cipherText && cipherText.length && site.type & MPResultTypeClassStateful) {
|
||||
NSString *plainText = [self mpwResultForSiteNamed:site.name ofType:site.type parameter:cipherText
|
||||
withCounter:MPCounterValueInitial variant:MPKeyPurposeAuthentication context:nil
|
||||
usingKey:importKey];
|
||||
if (plainText)
|
||||
[self savePassword:plainText toSite:site usingKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)importClearTextPassword:(NSString *)clearContent intoSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
- (NSDictionary *)queryForSite:(MPSiteEntity *)site {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
switch (site.type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
break;
|
||||
|
||||
case MPSiteTypeStoredPersonal: {
|
||||
[self savePassword:clearContent toSite:site usingKey:siteKey];
|
||||
break;
|
||||
return [PearlKeyChain createQueryForClass:kSecClassGenericPassword attributes:@{
|
||||
(__bridge id)kSecAttrService: site.type & MPSiteFeatureDevicePrivate? @"DevicePrivate": @"Private",
|
||||
(__bridge id)kSecAttrAccount: site.name
|
||||
} matches:nil];
|
||||
}
|
||||
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
break;
|
||||
}
|
||||
}
|
||||
- (NSString *)exportPasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)key {
|
||||
|
||||
- (NSString *)exportPasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
|
||||
|
||||
NSAssert( [[siteKey keyIDForAlgorithm:site.user.algorithm] isEqualToData:site.user.keyID], @"Site does not belong to current user." );
|
||||
if (!(site.type & MPSiteFeatureExportContent))
|
||||
return nil;
|
||||
|
||||
NSString *result = nil;
|
||||
switch (site.type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPSiteTypeGeneratedPhrase: {
|
||||
result = nil;
|
||||
break;
|
||||
NSDictionary *siteQuery = [self queryForSite:site];
|
||||
NSData *state = [PearlKeyChain dataOfItemForQuery:siteQuery];
|
||||
return [state?: ((MPStoredSiteEntity *)site).contentObject encodeBase64];
|
||||
}
|
||||
|
||||
case MPSiteTypeStoredPersonal: {
|
||||
if (![site isKindOfClass:[MPStoredSiteEntity class]]) {
|
||||
wrn( @"Site with stored type %lu is not an MPStoredSiteEntity, but a %@.",
|
||||
(long)site.type, [site class] );
|
||||
break;
|
||||
}
|
||||
result = [((MPStoredSiteEntity *)site).contentObject encodeBase64];
|
||||
break;
|
||||
}
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPResultType)type byAttacker:(MPAttacker)attacker {
|
||||
|
||||
case MPSiteTypeStoredDevicePrivate: {
|
||||
result = nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)migrateExplicitly:(BOOL)explicit {
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDictionary *)queryForDevicePrivateSiteNamed:(NSString *)name {
|
||||
|
||||
return [PearlKeyChain createQueryForClass:kSecClassGenericPassword
|
||||
attributes:@{
|
||||
(__bridge id)kSecAttrService: @"DevicePrivate",
|
||||
(__bridge id)kSecAttrAccount: name
|
||||
}
|
||||
matches:nil];
|
||||
}
|
||||
|
||||
- (NSString *)decryptContent:(NSData *)encryptedContent usingKey:(MPKey *)key {
|
||||
|
||||
if (!key)
|
||||
return nil;
|
||||
NSData *decryptedContent = nil;
|
||||
if ([encryptedContent length]) {
|
||||
NSData *encryptionKey = [key keyForAlgorithm:self trimmedLength:PearlCryptKeySize];
|
||||
decryptedContent = [encryptedContent decryptWithSymmetricKey:encryptionKey padding:YES];
|
||||
}
|
||||
if (!decryptedContent)
|
||||
return nil;
|
||||
|
||||
return [[NSString alloc] initWithBytes:decryptedContent.bytes length:decryptedContent.length encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPSiteType)type byAttacker:(MPAttacker)attacker {
|
||||
|
||||
if (!(type & MPSiteTypeClassGenerated))
|
||||
if (!(type & MPResultTypeClassTemplate))
|
||||
return NO;
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
return NO;
|
||||
|
||||
if (!explicit) {
|
||||
if (site.type & MPSiteTypeClassGenerated) {
|
||||
if (site.type & MPResultTypeClassTemplate) {
|
||||
// This migration requires explicit permission for types of the generated class.
|
||||
site.requiresExplicitMigration = YES;
|
||||
return NO;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
return NO;
|
||||
|
||||
if (!explicit) {
|
||||
if (site.type & MPSiteTypeClassGenerated && site.name.length != [site.name dataUsingEncoding:NSUTF8StringEncoding].length) {
|
||||
if (site.type & MPResultTypeClassTemplate && site.name.length != [site.name dataUsingEncoding:NSUTF8StringEncoding].length) {
|
||||
// This migration requires explicit permission for types of the generated class.
|
||||
site.requiresExplicitMigration = YES;
|
||||
return NO;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
return NO;
|
||||
|
||||
if (!explicit) {
|
||||
if (site.type & MPSiteTypeClassGenerated &&
|
||||
if (site.type & MPResultTypeClassTemplate &&
|
||||
site.user.name.length != [site.user.name dataUsingEncoding:NSUTF8StringEncoding].length) {
|
||||
// This migration requires explicit permission for types of the generated class.
|
||||
site.requiresExplicitMigration = YES;
|
||||
|
||||
@@ -248,9 +248,9 @@
|
||||
#endif
|
||||
|
||||
for (MPSiteEntity *site in user.sites) {
|
||||
if (site.type & MPSiteTypeClassStored) {
|
||||
if (site.type & MPResultTypeClassStateful) {
|
||||
NSString *content;
|
||||
while (!(content = [site.algorithm storedPasswordForSite:(MPStoredSiteEntity *)site usingKey:recoverKey])) {
|
||||
while (!(content = [site.algorithm resolvePasswordForSite:(MPStoredSiteEntity *)site usingKey:recoverKey])) {
|
||||
// Failed to decrypt site with the current recoveryKey. Ask user for a new one to use.
|
||||
NSString *masterPassword = nil;
|
||||
|
||||
|
||||
@@ -20,14 +20,6 @@
|
||||
|
||||
#import "MPFixable.h"
|
||||
|
||||
typedef NS_ENUM( NSUInteger, MPImportResult ) {
|
||||
MPImportResultSuccess,
|
||||
MPImportResultCancelled,
|
||||
MPImportResultInvalidPassword,
|
||||
MPImportResultMalformedInput,
|
||||
MPImportResultInternalError,
|
||||
};
|
||||
|
||||
@interface MPAppDelegate_Shared(Store)
|
||||
|
||||
+ (NSManagedObjectContext *)managedObjectContextForMainThreadIfReady;
|
||||
@@ -42,10 +34,13 @@ typedef NS_ENUM( NSUInteger, MPImportResult ) {
|
||||
|
||||
/** @param completion The block to execute after adding the site, executed from the main thread with the new site in the main MOC. */
|
||||
- (void)addSiteNamed:(NSString *)siteName completion:(void ( ^ )(MPSiteEntity *site, NSManagedObjectContext *context))completion;
|
||||
- (MPSiteEntity *)changeSite:(MPSiteEntity *)site saveInContext:(NSManagedObjectContext *)context toType:(MPSiteType)type;
|
||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||
- (MPSiteEntity *)changeSite:(MPSiteEntity *)site saveInContext:(NSManagedObjectContext *)context toType:(MPResultType)type;
|
||||
- (void)importSites:(NSString *)importData
|
||||
askImportPassword:(NSString *( ^ )(NSString *userName))importPassword
|
||||
askUserPassword:(NSString *( ^ )(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword;
|
||||
- (NSString *)exportSitesRevealPasswords:(BOOL)revealPasswords;
|
||||
askUserPassword:(NSString *( ^ )(NSString *userName))userPassword
|
||||
result:(void ( ^ )(NSError *error))resultBlock;
|
||||
- (void)exportSitesRevealPasswords:(BOOL)revealPasswords
|
||||
askExportPassword:(NSString *( ^ )(NSString *userName))askImportPassword
|
||||
result:(void ( ^ )(NSString *mpsites, NSError *error))resultBlock;
|
||||
|
||||
@end
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "mpw-marshall.h"
|
||||
#import "mpw-util.h"
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#define STORE_OPTIONS NSPersistentStoreFileProtectionKey : NSFileProtectionComplete,
|
||||
@@ -489,7 +490,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
return;
|
||||
}
|
||||
|
||||
MPSiteType type = activeUser.defaultType;
|
||||
MPResultType type = activeUser.defaultType;
|
||||
id<MPAlgorithm> algorithm = MPAlgorithmDefault;
|
||||
Class entityType = [algorithm classOfType:type];
|
||||
|
||||
@@ -506,7 +507,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
}];
|
||||
}
|
||||
|
||||
- (MPSiteEntity *)changeSite:(MPSiteEntity *)site saveInContext:(NSManagedObjectContext *)context toType:(MPSiteType)type {
|
||||
- (MPSiteEntity *)changeSite:(MPSiteEntity *)site saveInContext:(NSManagedObjectContext *)context toType:(MPResultType)type {
|
||||
|
||||
if (site.type == type)
|
||||
return site;
|
||||
@@ -539,328 +540,214 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
return site;
|
||||
}
|
||||
|
||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||
- (void)importSites:(NSString *)importData
|
||||
askImportPassword:(NSString *( ^ )(NSString *userName))importPassword
|
||||
askUserPassword:(NSString *( ^ )(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))userPassword {
|
||||
askUserPassword:(NSString *( ^ )(NSString *userName))userPassword
|
||||
result:(void ( ^ )(NSError *error))resultBlock {
|
||||
|
||||
NSAssert( ![[NSThread currentThread] isMainThread], @"This method should not be invoked from the main thread." );
|
||||
|
||||
__block MPImportResult result = MPImportResultCancelled;
|
||||
do {
|
||||
if ([MPAppDelegate_Shared managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
result = [self importSites:importedSitesString askImportPassword:importPassword askUserPassword:userPassword
|
||||
NSError *error = [self importSites:importData askImportPassword:importPassword askUserPassword:userPassword
|
||||
saveInContext:context];
|
||||
PearlMainQueue( ^{
|
||||
resultBlock( error );
|
||||
} );
|
||||
}])
|
||||
break;
|
||||
usleep( (useconds_t)(USEC_PER_SEC * 0.2) );
|
||||
} while (YES);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||
- (NSError *)importSites:(NSString *)importData
|
||||
askImportPassword:(NSString *( ^ )(NSString *userName))askImportPassword
|
||||
askUserPassword:(NSString *( ^ )(NSString *userName, NSUInteger importCount, NSUInteger deleteCount))askUserPassword
|
||||
askUserPassword:(NSString *( ^ )(NSString *userName))askUserPassword
|
||||
saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
// Compile patterns.
|
||||
static NSRegularExpression *headerPattern;
|
||||
static NSArray *sitePatterns;
|
||||
NSError *error = nil;
|
||||
if (!headerPattern) {
|
||||
headerPattern = [[NSRegularExpression alloc]
|
||||
initWithPattern:@"^#[[:space:]]*([^:]+): (.*)"
|
||||
options:(NSRegularExpressionOptions)0 error:&error];
|
||||
if (error) {
|
||||
MPError( error, @"Error loading the header pattern." );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
if (!sitePatterns) {
|
||||
sitePatterns = @[
|
||||
[[NSRegularExpression alloc] // Format 0
|
||||
initWithPattern:@"^([^ ]+) +([[:digit:]]+) +([[:digit:]]+)(:[[:digit:]]+)? +([^\t]+)\t(.*)"
|
||||
options:(NSRegularExpressionOptions)0 error:&error],
|
||||
[[NSRegularExpression alloc] // Format 1
|
||||
initWithPattern:@"^([^ ]+) +([[:digit:]]+) +([[:digit:]]+)(:[[:digit:]]+)?(:[[:digit:]]+)? +([^\t]*)\t *([^\t]+)\t(.*)"
|
||||
options:(NSRegularExpressionOptions)0 error:&error]
|
||||
];
|
||||
if (error) {
|
||||
MPError( error, @"Error loading the site patterns." );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
// Read metadata for the import file.
|
||||
MPMarshallInfo *info = mpw_marshall_read_info( importData.UTF8String );
|
||||
if (info->format == MPMarshallFormatNone)
|
||||
return MPError( ([NSError errorWithDomain:MPErrorDomain code:MPErrorMarshallCode userInfo:@{
|
||||
@"type" : @(MPMarshallErrorFormat),
|
||||
NSLocalizedDescriptionKey: @"This is not a Master Password import file.",
|
||||
}]), @"While importing sites." );
|
||||
|
||||
// Get master password for import file.
|
||||
MPKey *importKey;
|
||||
NSString *importMasterPassword;
|
||||
do {
|
||||
importMasterPassword = askImportPassword( @(info->fullName) );
|
||||
if (!importMasterPassword) {
|
||||
inf( @"Import cancelled." );
|
||||
mpw_marshal_info_free( &info );
|
||||
return MPError( ([NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]), @"" );
|
||||
}
|
||||
|
||||
importKey = [[MPKey alloc] initForFullName:@(info->fullName) withMasterPassword:importMasterPassword];
|
||||
} while ([[[importKey keyIDForAlgorithm:MPAlgorithmForVersion( info->algorithm )] encodeHex]
|
||||
caseInsensitiveCompare:@(info->keyID)] != NSOrderedSame);
|
||||
|
||||
// Parse import data.
|
||||
inf( @"Importing sites." );
|
||||
NSUInteger importFormat = 0;
|
||||
__block MPUserEntity *user = nil;
|
||||
NSUInteger importAvatar = NSNotFound;
|
||||
NSData *importKeyID = nil;
|
||||
NSString *importBundleVersion = nil, *importUserName = nil;
|
||||
id<MPAlgorithm> importAlgorithm = nil;
|
||||
MPSiteType importDefaultType = (MPSiteType)0;
|
||||
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
|
||||
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
|
||||
NSMutableSet *sitesToDelete = [NSMutableSet set];
|
||||
NSMutableArray *importedSiteSites = [NSMutableArray arrayWithCapacity:[importedSiteLines count]];
|
||||
NSFetchRequest *siteFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
|
||||
for (NSString *importedSiteLine in importedSiteLines) {
|
||||
if ([importedSiteLine hasPrefix:@"#"]) {
|
||||
// Comment or header
|
||||
if (!headerStarted) {
|
||||
if ([importedSiteLine isEqualToString:@"##"])
|
||||
headerStarted = YES;
|
||||
continue;
|
||||
}
|
||||
if (headerEnded)
|
||||
continue;
|
||||
if ([importedSiteLine isEqualToString:@"##"]) {
|
||||
headerEnded = YES;
|
||||
continue;
|
||||
}
|
||||
MPMarshallError importError = { .type = MPMarshallSuccess };
|
||||
MPMarshalledUser *importUser = mpw_marshall_read( importData.UTF8String, info->format, importMasterPassword.UTF8String, &importError );
|
||||
mpw_marshal_info_free( &info );
|
||||
|
||||
// Header
|
||||
if ([headerPattern numberOfMatchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] != 1) {
|
||||
err( @"Invalid header format in line: %@", importedSiteLine );
|
||||
return MPImportResultMalformedInput;
|
||||
}
|
||||
NSTextCheckingResult *headerSites = [[headerPattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
|
||||
NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
|
||||
|
||||
if ([headerName isEqualToString:@"Format"]) {
|
||||
importFormat = (NSUInteger)[headerValue integerValue];
|
||||
if (importFormat >= [sitePatterns count]) {
|
||||
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
if (([headerName isEqualToString:@"User Name"] || [headerName isEqualToString:@"Full Name"]) && !importUserName) {
|
||||
importUserName = headerValue;
|
||||
@try {
|
||||
if (!importUser || importError.type != MPMarshallSuccess)
|
||||
return MPError( ([NSError errorWithDomain:MPErrorDomain code:MPErrorMarshallCode userInfo:@{
|
||||
@"type" : @(importError.type),
|
||||
NSLocalizedDescriptionKey: @(importError.description),
|
||||
}]), @"While importing sites." );
|
||||
|
||||
// Find an existing user to update.
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", importUserName];
|
||||
userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", @(importUser->fullName)];
|
||||
NSArray *users = [context executeFetchRequest:userFetchRequest error:&error];
|
||||
if (!users) {
|
||||
MPError( error, @"While looking for user: %@.", importUserName );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
if ([users count] > 1) {
|
||||
err( @"While looking for user: %@, found more than one: %lu", importUserName, (unsigned long)[users count] );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
if (!users)
|
||||
return MPError( error, @"While looking for user: %@.", @(importUser->fullName) );
|
||||
if ([users count] > 1)
|
||||
return MPMakeError( @"While looking for user: %@, found more than one: %zu",
|
||||
@(importUser->fullName), (size_t)[users count] );
|
||||
|
||||
user = [users lastObject];
|
||||
dbg( @"Existing user? %@", [user debugDescription] );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Avatar"])
|
||||
importAvatar = (NSUInteger)[headerValue integerValue];
|
||||
if ([headerName isEqualToString:@"Key ID"])
|
||||
importKeyID = [headerValue decodeHex];
|
||||
if ([headerName isEqualToString:@"Version"]) {
|
||||
importBundleVersion = headerValue;
|
||||
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Algorithm"])
|
||||
importAlgorithm = MPAlgorithmForVersion( (MPAlgorithmVersion)[headerValue integerValue] );
|
||||
if ([headerName isEqualToString:@"Default Type"])
|
||||
importDefaultType = (MPSiteType)[headerValue integerValue];
|
||||
if ([headerName isEqualToString:@"Passwords"]) {
|
||||
if ([headerValue isEqualToString:@"VISIBLE"])
|
||||
clearText = YES;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (!headerEnded)
|
||||
continue;
|
||||
if (![importUserName length])
|
||||
return MPImportResultMalformedInput;
|
||||
if (![importedSiteLine length])
|
||||
continue;
|
||||
|
||||
// Site
|
||||
NSRegularExpression *sitePattern = sitePatterns[importFormat];
|
||||
if ([sitePattern numberOfMatchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] != 1) {
|
||||
err( @"Invalid site format in line: %@", importedSiteLine );
|
||||
return MPImportResultMalformedInput;
|
||||
}
|
||||
NSTextCheckingResult *siteElements = [[sitePattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
NSString *lastUsed, *uses, *type, *version, *counter, *siteName, *loginName, *exportContent;
|
||||
switch (importFormat) {
|
||||
case 0:
|
||||
lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
if ([version length])
|
||||
version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
counter = @"";
|
||||
loginName = @"";
|
||||
siteName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
break;
|
||||
case 1:
|
||||
lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
if ([version length])
|
||||
version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
counter = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
if ([counter length])
|
||||
counter = [counter substringFromIndex:1]; // Strip the leading colon.
|
||||
loginName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
siteName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:7]];
|
||||
exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:8]];
|
||||
break;
|
||||
default:
|
||||
err( @"Unexpected import format: %lu", (unsigned long)importFormat );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
|
||||
// Find existing site.
|
||||
if (user) {
|
||||
siteFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", siteName, user];
|
||||
NSArray *existingSites = [context executeFetchRequest:siteFetchRequest error:&error];
|
||||
if (!existingSites) {
|
||||
MPError( error, @"Lookup of existing sites failed for site: %@, user: %@.", siteName, user.userID );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
if ([existingSites count]) {
|
||||
dbg( @"Existing sites: %@", existingSites );
|
||||
[sitesToDelete addObjectsFromArray:existingSites];
|
||||
}
|
||||
}
|
||||
[importedSiteSites addObject:@[ lastUsed, uses, type, version, counter, loginName, siteName, exportContent ]];
|
||||
dbg( @"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, counter=%@, loginName=%@, siteName=%@, exportContent=%@",
|
||||
lastUsed, uses, type, version, counter, loginName, siteName, exportContent );
|
||||
}
|
||||
|
||||
// Ask for confirmation to import these sites and the master password of the user.
|
||||
inf( @"Importing %lu sites, deleting %lu sites, for user: %@", (unsigned long)[importedSiteSites count],
|
||||
(unsigned long)[sitesToDelete count], [MPUserEntity idFor:importUserName] );
|
||||
NSString *userMasterPassword = askUserPassword( user? user.name: importUserName, [importedSiteSites count],
|
||||
[sitesToDelete count] );
|
||||
// Get master key for user.
|
||||
MPUserEntity *user = [users lastObject];
|
||||
MPKey *userKey = importKey;
|
||||
while (user && ![[userKey keyIDForAlgorithm:user.algorithm] isEqualToData:user.keyID]) {
|
||||
NSString *userMasterPassword = askUserPassword( user.name );
|
||||
if (!userMasterPassword) {
|
||||
inf( @"Import cancelled." );
|
||||
return MPImportResultCancelled;
|
||||
return MPError( ([NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]), @"" );
|
||||
}
|
||||
MPKey *userKey = [[MPKey alloc] initForFullName:user? user.name: importUserName withMasterPassword:userMasterPassword];
|
||||
if (user && ![[userKey keyIDForAlgorithm:user.algorithm] isEqualToData:user.keyID])
|
||||
return MPImportResultInvalidPassword;
|
||||
__block MPKey *importKey = userKey;
|
||||
if (importKeyID && ![[importKey keyIDForAlgorithm:importAlgorithm] isEqualToData:importKeyID])
|
||||
importKey = [[MPKey alloc] initForFullName:importUserName withMasterPassword:askImportPassword( importUserName )];
|
||||
if (importKeyID && ![[importKey keyIDForAlgorithm:importAlgorithm] isEqualToData:importKeyID])
|
||||
return MPImportResultInvalidPassword;
|
||||
|
||||
// Delete existing sites.
|
||||
if (sitesToDelete.count)
|
||||
[sitesToDelete enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
|
||||
inf( @"Deleting site: %@, it will be replaced by an imported site.", [obj name] );
|
||||
[context deleteObject:obj];
|
||||
}];
|
||||
userKey = [[MPKey alloc] initForFullName:@(importUser->fullName) withMasterPassword:userMasterPassword];
|
||||
}
|
||||
|
||||
// Make sure there is a user.
|
||||
if (user) {
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
if (importDefaultType)
|
||||
user.defaultType = importDefaultType;
|
||||
dbg( @"Updating User: %@", [user debugDescription] );
|
||||
// Update or create user.
|
||||
if (!user) {
|
||||
user = [MPUserEntity insertNewObjectInContext:context];
|
||||
user.name = @(importUser->fullName);
|
||||
}
|
||||
user.algorithm = MPAlgorithmForVersion( importUser->algorithm );
|
||||
user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
|
||||
user.avatar = importUser->avatar;
|
||||
user.defaultType = importUser->defaultType;
|
||||
user.lastUsed = [NSDate dateWithTimeIntervalSince1970:MAX( user.lastUsed.timeIntervalSince1970, importUser->lastUsed )];
|
||||
dbg( @"Importing user: %@", [user debugDescription] );
|
||||
|
||||
// Update or create sites.
|
||||
for (size_t s = 0; s < importUser->sites_count; ++s) {
|
||||
MPMarshalledSite *importSite = &importUser->sites[s];
|
||||
|
||||
// Find an existing site to update.
|
||||
NSFetchRequest *siteFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
|
||||
siteFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", @(importSite->name), user];
|
||||
NSArray *existingSites = [context executeFetchRequest:siteFetchRequest error:&error];
|
||||
if (!existingSites)
|
||||
return MPError( error, @"Lookup of existing sites failed for site: %@, user: %@", @(importSite->name), user.userID );
|
||||
if ([existingSites count])
|
||||
// Update existing site.
|
||||
for (MPSiteEntity *site in existingSites) {
|
||||
[self importSite:importSite protectedByKey:importKey intoSite:site usingKey:userKey];
|
||||
dbg( @"Updated site: %@", [site debugDescription] );
|
||||
}
|
||||
else {
|
||||
user = [MPUserEntity insertNewObjectInContext:context];
|
||||
user.name = importUserName;
|
||||
user.algorithm = MPAlgorithmDefault;
|
||||
user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
|
||||
user.defaultType = importDefaultType?: user.algorithm.defaultType;
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
dbg( @"Created User: %@", [user debugDescription] );
|
||||
}
|
||||
|
||||
// Import new sites.
|
||||
for (NSArray *siteElements in importedSiteSites) {
|
||||
NSDate *lastUsed = [[NSDateFormatter rfc3339DateFormatter] dateFromString:siteElements[0]];
|
||||
NSUInteger uses = (unsigned)[siteElements[1] integerValue];
|
||||
MPSiteType type = (MPSiteType)[siteElements[2] integerValue];
|
||||
MPAlgorithmVersion version = (MPAlgorithmVersion)[siteElements[3] integerValue];
|
||||
NSUInteger counter = [siteElements[4] length]? (unsigned)[siteElements[4] integerValue]: NSNotFound;
|
||||
NSString *loginName = [siteElements[5] length]? siteElements[5]: nil;
|
||||
NSString *siteName = siteElements[6];
|
||||
NSString *exportContent = siteElements[7];
|
||||
|
||||
// Create new site.
|
||||
id<MPAlgorithm> algorithm = MPAlgorithmForVersion( version );
|
||||
Class entityType = [algorithm classOfType:type];
|
||||
if (!entityType) {
|
||||
err( @"Invalid site type in import file: %@ has type %lu", siteName, (long)type );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
MPSiteEntity *site = (MPSiteEntity *)[entityType insertNewObjectInContext:context];
|
||||
site.name = siteName;
|
||||
site.loginName = loginName;
|
||||
site.user = user;
|
||||
site.type = type;
|
||||
site.uses = uses;
|
||||
site.lastUsed = lastUsed;
|
||||
site.algorithm = algorithm;
|
||||
if ([exportContent length]) {
|
||||
if (clearText)
|
||||
[site.algorithm importClearTextPassword:exportContent intoSite:site usingKey:userKey];
|
||||
else
|
||||
[site.algorithm importProtectedPassword:exportContent protectedByKey:importKey intoSite:site usingKey:userKey];
|
||||
}
|
||||
if ([site isKindOfClass:[MPGeneratedSiteEntity class]] && counter != NSNotFound)
|
||||
((MPGeneratedSiteEntity *)site).counter = counter;
|
||||
id<MPAlgorithm> algorithm = MPAlgorithmForVersion( importSite->algorithm );
|
||||
Class entityType = [algorithm classOfType:importSite->type];
|
||||
if (!entityType)
|
||||
return MPMakeError( @"Invalid site type in import file: %@ has type %lu", @(importSite->name), (long)importSite->type );
|
||||
|
||||
dbg( @"Created Site: %@", [site debugDescription] );
|
||||
MPSiteEntity *site = (MPSiteEntity *)[entityType insertNewObjectInContext:context];
|
||||
site.user = user;
|
||||
|
||||
[self importSite:importSite protectedByKey:importKey intoSite:site usingKey:userKey];
|
||||
dbg( @"Created site: %@", [site debugDescription] );
|
||||
}
|
||||
}
|
||||
|
||||
if (![context saveToStore])
|
||||
return MPImportResultInternalError;
|
||||
return MPMakeError( @"Failed saving imported changes." );
|
||||
|
||||
inf( @"Import completed successfully." );
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPSitesImportedNotification object:nil userInfo:@{
|
||||
MPSitesImportedNotificationUserKey: user
|
||||
}];
|
||||
|
||||
return MPImportResultSuccess;
|
||||
return nil;
|
||||
}
|
||||
@finally {
|
||||
mpw_marshal_free( &importUser );
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)exportSitesRevealPasswords:(BOOL)revealPasswords {
|
||||
- (void)importSite:(const MPMarshalledSite *)importSite protectedByKey:(MPKey *)importKey intoSite:(MPSiteEntity *)site
|
||||
usingKey:(MPKey *)userKey {
|
||||
|
||||
MPUserEntity *activeUser = [self activeUserForMainThread];
|
||||
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", activeUser.userID );
|
||||
site.name = @(importSite->name);
|
||||
if (importSite->content)
|
||||
[site.algorithm importPassword:@(importSite->content) protectedByKey:importKey intoSite:site usingKey:userKey];
|
||||
site.type = importSite->type;
|
||||
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
((MPGeneratedSiteEntity *)site).counter = importSite->counter;
|
||||
site.algorithm = MPAlgorithmForVersion( importSite->algorithm );
|
||||
site.loginName = importSite->loginContent? @(importSite->loginContent): nil;
|
||||
site.loginGenerated = importSite->loginType & MPResultTypeClassTemplate;
|
||||
site.url = importSite->url? @(importSite->url): nil;
|
||||
site.uses = importSite->uses;
|
||||
site.lastUsed = [NSDate dateWithTimeIntervalSince1970:importSite->lastUsed];
|
||||
}
|
||||
|
||||
MPMarshalledUser exportUser = mpw_marshall_user( activeUser.name.UTF8String,
|
||||
[self.key keyForAlgorithm:activeUser.algorithm], activeUser.algorithm.version );
|
||||
exportUser.avatar = activeUser.avatar;
|
||||
exportUser.defaultType = activeUser.defaultType;
|
||||
exportUser.lastUsed = (time_t)activeUser.lastUsed.timeIntervalSince1970;
|
||||
- (void)exportSitesRevealPasswords:(BOOL)revealPasswords
|
||||
askExportPassword:(NSString *( ^ )(NSString *userName))askImportPassword
|
||||
result:(void ( ^ )(NSString *mpsites, NSError *error))resultBlock {
|
||||
|
||||
[MPAppDelegate_Shared managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPUserEntity *user = [self activeUserInContext:context];
|
||||
NSString *masterPassword = askImportPassword( user.name );
|
||||
|
||||
for (MPSiteEntity *site in activeUser.sites) {
|
||||
MPMarshalledSite exportSite = mpw_marshall_site( &exportUser,
|
||||
site.name.UTF8String, site.type, site.counter, site.algorithm.version );
|
||||
exportSite.loginName = site.loginName.UTF8String;
|
||||
exportSite.url = site.url.UTF8String;
|
||||
exportSite.uses = site.uses;
|
||||
exportSite.lastUsed = (time_t)site.lastUsed.timeIntervalSince1970;
|
||||
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", user.userID );
|
||||
MPMarshalledUser *exportUser = mpw_marshall_user( user.name.UTF8String, masterPassword.UTF8String, user.algorithm.version );
|
||||
exportUser->redacted = !revealPasswords;
|
||||
exportUser->avatar = (unsigned int)user.avatar;
|
||||
exportUser->defaultType = user.defaultType;
|
||||
exportUser->lastUsed = (time_t)user.lastUsed.timeIntervalSince1970;
|
||||
|
||||
for (MPSiteEntity *site in user.sites) {
|
||||
MPCounterValue counter = MPCounterValueInitial;
|
||||
if ([site isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
counter = ((MPGeneratedSiteEntity *)site).counter;
|
||||
NSString *content = revealPasswords
|
||||
? [site.algorithm exportPasswordForSite:site usingKey:self.key]
|
||||
: [site.algorithm resolvePasswordForSite:site usingKey:self.key];
|
||||
|
||||
MPMarshalledSite *exportSite = mpw_marshall_site( exportUser,
|
||||
site.name.UTF8String, site.type, counter, site.algorithm.version );
|
||||
exportSite->content = content.UTF8String;
|
||||
exportSite->loginContent = site.loginName.UTF8String;
|
||||
exportSite->loginType = site.loginGenerated? MPResultTypeTemplateName: MPResultTypeStatefulPersonal;
|
||||
exportSite->url = site.url.UTF8String;
|
||||
exportSite->uses = (unsigned int)site.uses;
|
||||
exportSite->lastUsed = (time_t)site.lastUsed.timeIntervalSince1970;
|
||||
|
||||
for (MPSiteQuestionEntity *siteQuestion in site.questions)
|
||||
mpw_marshal_question( &exportSite, siteQuestion.keyword.UTF8String );
|
||||
mpw_marshal_question( exportSite, siteQuestion.keyword.UTF8String );
|
||||
}
|
||||
|
||||
mpw_marshall_write( &export, MPMarshallFormatFlat, exportUser );
|
||||
char *export = NULL;
|
||||
MPMarshallError exportError = (MPMarshallError){ .type= MPMarshallSuccess };
|
||||
mpw_marshall_write( &export, MPMarshallFormatFlat, exportUser, &exportError );
|
||||
NSString *mpsites = nil;
|
||||
if (export && exportError.type == MPMarshallSuccess)
|
||||
mpsites = [NSString stringWithCString:export encoding:NSUTF8StringEncoding];
|
||||
mpw_free_string( &export );
|
||||
|
||||
resultBlock( mpsites, exportError.type == MPMarshallSuccess? nil:
|
||||
[NSError errorWithDomain:MPErrorDomain code:MPErrorMarshallCode userInfo:@{
|
||||
@"type" : @(exportError.type),
|
||||
NSLocalizedDescriptionKey: @(exportError.description),
|
||||
}] );
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
@interface MPSiteEntity(MP)<MPFixable>
|
||||
|
||||
@property(assign) BOOL loginGenerated;
|
||||
@property(assign) MPSiteType type;
|
||||
@property(assign) MPResultType type;
|
||||
@property(readonly) NSString *typeName;
|
||||
@property(readonly) NSString *typeShortName;
|
||||
@property(readonly) NSString *typeClassName;
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
@interface MPGeneratedSiteEntity(MP)
|
||||
|
||||
@property(assign) NSUInteger counter;
|
||||
@property(assign) MPCounterValue counter;
|
||||
|
||||
@end
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
@property(assign) NSUInteger avatar;
|
||||
@property(assign) BOOL saveKey;
|
||||
@property(assign) BOOL touchID;
|
||||
@property(assign) MPSiteType defaultType;
|
||||
@property(assign) MPResultType defaultType;
|
||||
@property(readonly) NSString *userID;
|
||||
@property(strong) id<MPAlgorithm> algorithm;
|
||||
|
||||
|
||||
@@ -82,9 +82,9 @@
|
||||
return MPFixableResultNoProblems;
|
||||
}
|
||||
|
||||
- (MPSiteType)type {
|
||||
- (MPResultType)type {
|
||||
|
||||
return (MPSiteType)[self.type_ unsignedIntegerValue];
|
||||
return (MPResultType)[self.type_ unsignedIntegerValue];
|
||||
}
|
||||
|
||||
- (void)setLoginGenerated:(BOOL)aLoginGenerated {
|
||||
@@ -97,7 +97,7 @@
|
||||
return [self.loginGenerated_ boolValue];
|
||||
}
|
||||
|
||||
- (void)setType:(MPSiteType)aType {
|
||||
- (void)setType:(MPResultType)aType {
|
||||
|
||||
self.type_ = @(aType);
|
||||
}
|
||||
@@ -251,7 +251,7 @@
|
||||
|
||||
MPFixableResult result = [super findAndFixInconsistenciesInContext:context];
|
||||
|
||||
if (!self.type || self.type == (MPSiteType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
|
||||
if (!self.type || self.type == (MPResultType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
|
||||
// Invalid self.type
|
||||
result = MPApplyFix( result, ^MPFixableResult {
|
||||
wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.",
|
||||
@@ -259,7 +259,7 @@
|
||||
self.type = self.user.defaultType;
|
||||
return MPFixableResultProblemsFixed;
|
||||
} );
|
||||
if (!self.type || self.type == (MPSiteType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
|
||||
if (!self.type || self.type == (MPResultType)NSNotFound || ![[self.algorithm allTypes] containsObject:self.type_])
|
||||
// Invalid self.user.defaultType
|
||||
result = MPApplyFix( result, ^MPFixableResult {
|
||||
wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.",
|
||||
@@ -270,7 +270,7 @@
|
||||
if (![self isKindOfClass:[self.algorithm classOfType:self.type]])
|
||||
// Mismatch between self.type and self.class
|
||||
result = MPApplyFix( result, ^MPFixableResult {
|
||||
for (MPSiteType newType = self.type; self.type != (newType = [self.algorithm nextType:newType]);)
|
||||
for (MPResultType newType = self.type; self.type != (newType = [self.algorithm nextType:newType]);)
|
||||
if ([self isKindOfClass:[self.algorithm classOfType:newType]]) {
|
||||
wrn( @"Mismatching type for: %@ of %@, type: %lu, class: %@. Will use %ld instead.",
|
||||
self.name, self.user.name, (long)self.type, self.class, (long)newType );
|
||||
@@ -286,12 +286,12 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSUInteger)counter {
|
||||
- (MPCounterValue)counter {
|
||||
|
||||
return [self.counter_ unsignedIntegerValue];
|
||||
return (MPCounterValue)[self.counter_ unsignedIntegerValue];
|
||||
}
|
||||
|
||||
- (void)setCounter:(NSUInteger)aCounter {
|
||||
- (void)setCounter:(MPCounterValue)aCounter {
|
||||
|
||||
self.counter_ = @(aCounter);
|
||||
}
|
||||
@@ -354,12 +354,12 @@
|
||||
self.touchID_ = @(aTouchID);
|
||||
}
|
||||
|
||||
- (MPSiteType)defaultType {
|
||||
- (MPResultType)defaultType {
|
||||
|
||||
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: self.algorithm.defaultType;
|
||||
return (MPResultType)[self.defaultType_ unsignedIntegerValue]?: self.algorithm.defaultType;
|
||||
}
|
||||
|
||||
- (void)setDefaultType:(MPSiteType)aDefaultType {
|
||||
- (void)setDefaultType:(MPResultType)aDefaultType {
|
||||
|
||||
self.defaultType_ = @(aDefaultType);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
__BEGIN_DECLS
|
||||
extern NSString *const MPErrorDomain;
|
||||
extern NSInteger const MPErrorHangCode;
|
||||
extern NSInteger const MPErrorMarshallCode;
|
||||
|
||||
extern NSString *const MPSignedInNotification;
|
||||
extern NSString *const MPSignedOutNotification;
|
||||
@@ -38,16 +39,26 @@ __END_DECLS
|
||||
|
||||
#ifdef CRASHLYTICS
|
||||
#define MPError(error_, message, ...) ({ \
|
||||
err( message @"%@%@", ##__VA_ARGS__, error_? @"\n": @"", [error_ fullDescription]?: @"" ); \
|
||||
NSError *__error = error_; \
|
||||
err( message @"%@%@", ##__VA_ARGS__, __error && [message length]? @"\n": @"", [__error fullDescription]?: @"" ); \
|
||||
\
|
||||
if ([[MPConfig get].sendInfo boolValue]) { \
|
||||
[[Crashlytics sharedInstance] recordError:error_ withAdditionalUserInfo:@{ \
|
||||
if (__error && [[MPConfig get].sendInfo boolValue]) { \
|
||||
[[Crashlytics sharedInstance] recordError:__error withAdditionalUserInfo:@{ \
|
||||
@"location": strf( @"%@:%d %@", @(basename((char *)__FILE__)), __LINE__, NSStringFromSelector(_cmd) ), \
|
||||
}]; \
|
||||
} \
|
||||
__error; \
|
||||
})
|
||||
#else
|
||||
#define MPError(error_, message, ...) ({ \
|
||||
err( message @"%@%@", ##__VA_ARGS__, error_? @"\n": @"", [error_ fullDescription]?: @"" ); \
|
||||
NSError *__error = error_; \
|
||||
err( message @"%@%@", ##__VA_ARGS__, __error? @"\n": @"", [__error fullDescription]?: @"" ); \
|
||||
__error; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define MPMakeError(message, ...) ({ \
|
||||
MPError( [NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{ \
|
||||
NSLocalizedDescriptionKey: strf( message, ##__VA_ARGS__ ) \
|
||||
}], @"" ); \
|
||||
})
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
NSString *const MPErrorDomain = @"MPErrorDomain";
|
||||
NSInteger const MPErrorHangCode = 1;
|
||||
NSInteger const MPErrorMarshallCode = 1;
|
||||
|
||||
NSString *const MPSignedInNotification = @"MPSignedInNotification";
|
||||
NSString *const MPSignedOutNotification = @"MPSignedOutNotification";
|
||||
|
||||
@@ -269,23 +269,22 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[openPanel close];
|
||||
|
||||
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
|
||||
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
|
||||
if (error)
|
||||
MPError( error, @"While reading imported sites from %@.", url );
|
||||
^(NSData *importedSitesData, NSURLResponse *response, NSError *urlError) {
|
||||
if (urlError)
|
||||
[[NSAlert alertWithError:MPError( urlError, @"While reading imported sites from %@.", url )] runModal];
|
||||
if (!importedSitesData)
|
||||
return;
|
||||
|
||||
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
|
||||
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
||||
[self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
PearlMainQueueWait( ^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Unlock"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
alert.messageText = @"Import File's Master Password";
|
||||
alert.informativeText = strf( @"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName );
|
||||
alert.messageText = strf( @"Importing Sites For\n%@", userName );
|
||||
alert.informativeText = @"Enter the master password used to create this export file.";
|
||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert layout];
|
||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||
@@ -293,16 +292,15 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
} );
|
||||
|
||||
return masterPassword;
|
||||
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
|
||||
} askUserPassword:^NSString *(NSString *userName) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
PearlMainQueueWait( ^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Import"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
alert.messageText = strf( @"Master Password for\n%@", userName );
|
||||
alert.informativeText = strf( @"Imports %lu sites, overwriting %lu.",
|
||||
(unsigned long)importCount, (unsigned long)deleteCount );
|
||||
alert.messageText = strf( @"Master Password For\n%@", userName );
|
||||
alert.informativeText = @"Enter the current master password for this user.";
|
||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert layout];
|
||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||
@@ -310,37 +308,12 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
} );
|
||||
|
||||
return masterPassword;
|
||||
}];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
switch (result) {
|
||||
case MPImportResultSuccess: {
|
||||
} result:^(NSError *error) {
|
||||
[self updateUsers];
|
||||
|
||||
NSAlert *alert = [NSAlert new];
|
||||
alert.messageText = @"Successfully imported sites.";
|
||||
[alert runModal];
|
||||
break;
|
||||
}
|
||||
case MPImportResultCancelled:
|
||||
break;
|
||||
case MPImportResultInternalError:
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Import failed because of an internal error."
|
||||
}]] runModal];
|
||||
break;
|
||||
case MPImportResultMalformedInput:
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"The import doesn't look like a Master Password export."
|
||||
}]] runModal];
|
||||
break;
|
||||
case MPImportResultInvalidPassword:
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey: @"Incorrect master password for the import sites."
|
||||
}]] runModal];
|
||||
break;
|
||||
}
|
||||
} );
|
||||
if (error && !(error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError))
|
||||
[[NSAlert alertWithError:error] runModal];
|
||||
}];
|
||||
}] resume];
|
||||
}
|
||||
|
||||
@@ -509,25 +482,43 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
|
||||
return;
|
||||
|
||||
NSError *coordinateError = nil;
|
||||
NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords];
|
||||
[[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:savePanel.URL options:0
|
||||
error:&coordinateError byAccessor:
|
||||
^(NSURL *newURL) {
|
||||
NSError *writeError = nil;
|
||||
if (![exportedSites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
||||
MPError( writeError, @"Could not write to the export file." );
|
||||
|
||||
[self exportSitesRevealPasswords:revealPasswords
|
||||
askExportPassword:^NSString *(NSString *userName) {
|
||||
return PearlMainQueueAwait( ^id {
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Import"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
alert.messageText = strf( @"Master Password For\n%@", userName );
|
||||
alert.informativeText = @"Enter the current master password for this user.";
|
||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert layout];
|
||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||
return ((NSTextField *)alert.accessoryView).stringValue;
|
||||
else
|
||||
return nil;
|
||||
} );
|
||||
} result:^(NSString *mpsites, NSError *error) {
|
||||
if (!mpsites || error) {
|
||||
PearlMainQueue( ^{
|
||||
[[NSAlert alertWithError:writeError] runModal];
|
||||
[[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal];
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *coordinateError = nil;
|
||||
[[[NSFileCoordinator alloc] initWithFilePresenter:nil]
|
||||
coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) {
|
||||
NSError *writeError = nil;
|
||||
if (![mpsites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
||||
PearlMainQueue( ^{
|
||||
[[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal];
|
||||
} );
|
||||
}];
|
||||
if (coordinateError) {
|
||||
MPError( coordinateError, @"Write access to the export file could not be obtained." );
|
||||
if (coordinateError)
|
||||
PearlMainQueue( ^{
|
||||
[[NSAlert alertWithError:coordinateError] runModal];
|
||||
[[NSAlert alertWithError:MPError( coordinateError, @"Could not gain access to the export file." )] runModal];
|
||||
} );
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateUsers {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
@property(nonatomic) NSString *name;
|
||||
@property(nonatomic) NSAttributedString *displayedName;
|
||||
@property(nonatomic) MPSiteType type;
|
||||
@property(nonatomic) MPResultType type;
|
||||
@property(nonatomic) NSString *typeName;
|
||||
@property(nonatomic) NSString *content;
|
||||
@property(nonatomic) NSString *displayedContent;
|
||||
@@ -36,7 +36,7 @@
|
||||
@property(nonatomic) NSString *loginName;
|
||||
@property(nonatomic) BOOL loginGenerated;
|
||||
@property(nonatomic) NSNumber *uses;
|
||||
@property(nonatomic) NSUInteger counter;
|
||||
@property(nonatomic) MPCounterValue counter;
|
||||
@property(nonatomic) NSDate *lastUsed;
|
||||
@property(nonatomic) id<MPAlgorithm> algorithm;
|
||||
@property(nonatomic) MPAlgorithmVersion algorithmVersion;
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
self.type = entity.type;
|
||||
self.typeName = entity.typeName;
|
||||
self.uses = entity.uses_;
|
||||
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: 0;
|
||||
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: MPCounterValueInitial;
|
||||
self.loginGenerated = entity.loginGenerated;
|
||||
|
||||
// Find all password types and the index of the current type amongst them.
|
||||
@@ -104,7 +104,7 @@
|
||||
self.type = user.defaultType;
|
||||
self.typeName = [self.algorithm nameOfType:self.type];
|
||||
self.uses = @0;
|
||||
self.counter = 1;
|
||||
self.counter = MPCounterValueDefault;
|
||||
|
||||
// Find all password types and the index of the current type amongst them.
|
||||
[self updateContent];
|
||||
@@ -116,14 +116,14 @@
|
||||
return nil;
|
||||
|
||||
NSError *error;
|
||||
MPSiteEntity *entity = (MPSiteEntity *)[moc existingObjectWithID:self.entityOID error:&error];
|
||||
MPSiteEntity *entity = [moc existingObjectWithID:self.entityOID error:&error];
|
||||
if (!entity)
|
||||
MPError( error, @"Couldn't retrieve active site." );
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
- (void)setCounter:(NSUInteger)counter {
|
||||
- (void)setCounter:(MPCounterValue)counter {
|
||||
|
||||
if (self.counter == counter)
|
||||
return;
|
||||
@@ -210,12 +210,12 @@
|
||||
|
||||
- (BOOL)generated {
|
||||
|
||||
return self.type & MPSiteTypeClassGenerated;
|
||||
return self.type & MPResultTypeClassTemplate;
|
||||
}
|
||||
|
||||
- (BOOL)stored {
|
||||
|
||||
return self.type & MPSiteTypeClassStored;
|
||||
return self.type & MPResultTypeClassStateful;
|
||||
}
|
||||
|
||||
- (BOOL)transient {
|
||||
@@ -233,13 +233,13 @@
|
||||
else
|
||||
PearlNotMainQueue( ^{
|
||||
[self updatePasswordWithResult:
|
||||
[self.algorithm generatePasswordForSiteNamed:self.name ofType:self.type withCounter:self.counter
|
||||
[self.algorithm mpwTemplateForSiteNamed:self.name ofType:self.type withCounter:self.counter
|
||||
usingKey:[MPAppDelegate_Shared get].key]];
|
||||
[self updateLoginNameWithResult:
|
||||
[self.algorithm generateLoginForSiteNamed:self.name
|
||||
[self.algorithm mpwLoginForSiteNamed:self.name
|
||||
usingKey:[MPAppDelegate_Shared get].key]];
|
||||
[self updateAnswerWithResult:
|
||||
[self.algorithm generateAnswerForSiteNamed:self.name onQuestion:self.question
|
||||
[self.algorithm mpwAnswerForSiteNamed:self.name onQuestion:self.question
|
||||
usingKey:[MPAppDelegate_Shared get].key]];
|
||||
} );
|
||||
}
|
||||
@@ -252,7 +252,7 @@
|
||||
[entity resolveLoginUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
[self updateLoginNameWithResult:result];
|
||||
}];
|
||||
[self updateAnswerWithResult:[self.algorithm generateAnswerForSiteNamed:self.name onQuestion:self.question
|
||||
[self updateAnswerWithResult:[self.algorithm mpwAnswerForSiteNamed:self.name onQuestion:self.question
|
||||
usingKey:[MPAppDelegate_Shared get].key]];
|
||||
}
|
||||
|
||||
|
||||
@@ -373,10 +373,10 @@
|
||||
NSArray *types = [site.algorithm allTypes];
|
||||
[self.passwordTypesMatrix renewRows:(NSInteger)[types count] columns:1];
|
||||
for (NSUInteger t = 0; t < [types count]; ++t) {
|
||||
MPSiteType type = (MPSiteType)[types[t] unsignedIntegerValue];
|
||||
MPResultType type = (MPResultType)[types[t] unsignedIntegerValue];
|
||||
NSString *title = [site.algorithm nameOfType:type];
|
||||
if (type & MPSiteTypeClassGenerated)
|
||||
title = strf( @"%@ – %@", [site.algorithm generatePasswordForSiteNamed:site.name ofType:type withCounter:site.counter
|
||||
if (type & MPResultTypeClassTemplate)
|
||||
title = strf( @"%@ – %@", [site.algorithm mpwTemplateForSiteNamed:site.name ofType:type withCounter:site.counter
|
||||
usingKey:[MPMacAppDelegate get].key], title );
|
||||
|
||||
NSButtonCell *cell = [self.passwordTypesMatrix cellAtRow:(NSInteger)t column:0];
|
||||
@@ -397,7 +397,7 @@
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Save" button.
|
||||
MPSiteType type = (MPSiteType)[self.passwordTypesMatrix.selectedCell tag];
|
||||
MPResultType type = (MPResultType)[self.passwordTypesMatrix.selectedCell tag];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *entity = [[MPMacAppDelegate get] changeSite:[self.selectedSite entityInContext:context]
|
||||
saveInContext:context toType:type];
|
||||
|
||||
@@ -137,9 +137,9 @@
|
||||
- (void)updatePassword {
|
||||
|
||||
NSString *siteName = self.siteField.text;
|
||||
MPSiteType siteType = [self siteType];
|
||||
NSUInteger siteCounter = (NSUInteger)self.counterStepper.value;
|
||||
self.counterLabel.text = strf( @"%lu", (unsigned long)siteCounter );
|
||||
MPResultType siteType = [self siteType];
|
||||
MPCounterValue siteCounter = (MPCounterValue)self.counterStepper.value;
|
||||
self.counterLabel.text = strf( @"%u", siteCounter );
|
||||
|
||||
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
|
||||
[self.activity startAnimating];
|
||||
@@ -147,7 +147,7 @@
|
||||
[self.emergencyPasswordQueue addOperationWithBlock:^{
|
||||
NSString *sitePassword = nil;
|
||||
if (self.key && [siteName length])
|
||||
sitePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:siteName ofType:siteType withCounter:siteCounter
|
||||
sitePassword = [MPAlgorithmDefault mpwTemplateForSiteNamed:siteName ofType:siteType withCounter:siteCounter
|
||||
usingKey:self.key];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
@@ -157,21 +157,21 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (enum MPSiteType)siteType {
|
||||
- (MPResultType)siteType {
|
||||
|
||||
switch (self.typeControl.selectedSegmentIndex) {
|
||||
case 0:
|
||||
return MPSiteTypeGeneratedMaximum;
|
||||
return MPResultTypeTemplateMaximum;
|
||||
case 1:
|
||||
return MPSiteTypeGeneratedLong;
|
||||
return MPResultTypeTemplateLong;
|
||||
case 2:
|
||||
return MPSiteTypeGeneratedMedium;
|
||||
return MPResultTypeTemplateMedium;
|
||||
case 3:
|
||||
return MPSiteTypeGeneratedBasic;
|
||||
return MPResultTypeTemplateBasic;
|
||||
case 4:
|
||||
return MPSiteTypeGeneratedShort;
|
||||
return MPResultTypeTemplateShort;
|
||||
case 5:
|
||||
return MPSiteTypeGeneratedPIN;
|
||||
return MPResultTypeTemplatePIN;
|
||||
default:
|
||||
Throw( @"Unsupported type index: %ld", (long)self.typeControl.selectedSegmentIndex );
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@
|
||||
self.touchIDSwitch.on = activeUser.touchID;
|
||||
self.touchIDSwitch.enabled = self.savePasswordSwitch.on && [[MPiOSAppDelegate get] isFeatureUnlocked:MPProductTouchID];
|
||||
|
||||
MPSiteType defaultType = activeUser.defaultType;
|
||||
MPResultType defaultType = activeUser.defaultType;
|
||||
self.generated1TypeControl.selectedSegmentIndex = [self generated1SegmentIndexForType:defaultType];
|
||||
self.generated2TypeControl.selectedSegmentIndex = [self generated2SegmentIndexForType:defaultType];
|
||||
self.storedTypeControl.selectedSegmentIndex = [self storedSegmentIndexForType:defaultType];
|
||||
PearlNotMainQueue( ^{
|
||||
NSString *examplePassword = nil;
|
||||
if (defaultType & MPSiteTypeClassGenerated)
|
||||
examplePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:@"test" ofType:defaultType
|
||||
if (defaultType & MPResultTypeClassTemplate)
|
||||
examplePassword = [MPAlgorithmDefault mpwTemplateForSiteNamed:@"test" ofType:defaultType
|
||||
withCounter:1 usingKey:[MPiOSAppDelegate get].key];
|
||||
PearlMainQueue( ^{
|
||||
self.typeSamplePassword.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil;
|
||||
@@ -164,7 +164,7 @@
|
||||
if (sender != self.storedTypeControl)
|
||||
self.storedTypeControl.selectedSegmentIndex = -1;
|
||||
|
||||
MPSiteType defaultType = [self typeForSelectedSegment];
|
||||
MPResultType defaultType = [self typeForSelectedSegment];
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
[[MPiOSAppDelegate get] activeUserInContext:context].defaultType = defaultType;
|
||||
[context saveToStore];
|
||||
@@ -242,7 +242,7 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (MPSiteType)typeForSelectedSegment {
|
||||
- (MPResultType)typeForSelectedSegment {
|
||||
|
||||
NSInteger selectedGenerated1Index = self.generated1TypeControl.selectedSegmentIndex;
|
||||
NSInteger selectedGenerated2Index = self.generated2TypeControl.selectedSegmentIndex;
|
||||
@@ -250,30 +250,30 @@
|
||||
|
||||
switch (selectedGenerated1Index) {
|
||||
case 0:
|
||||
return MPSiteTypeGeneratedPhrase;
|
||||
return MPResultTypeTemplatePhrase;
|
||||
case 1:
|
||||
return MPSiteTypeGeneratedName;
|
||||
return MPResultTypeTemplateName;
|
||||
default:
|
||||
switch (selectedGenerated2Index) {
|
||||
case 0:
|
||||
return MPSiteTypeGeneratedMaximum;
|
||||
return MPResultTypeTemplateMaximum;
|
||||
case 1:
|
||||
return MPSiteTypeGeneratedLong;
|
||||
return MPResultTypeTemplateLong;
|
||||
case 2:
|
||||
return MPSiteTypeGeneratedMedium;
|
||||
return MPResultTypeTemplateMedium;
|
||||
case 3:
|
||||
return MPSiteTypeGeneratedBasic;
|
||||
return MPResultTypeTemplateBasic;
|
||||
case 4:
|
||||
return MPSiteTypeGeneratedShort;
|
||||
return MPResultTypeTemplateShort;
|
||||
case 5:
|
||||
return MPSiteTypeGeneratedPIN;
|
||||
return MPResultTypeTemplatePIN;
|
||||
default:
|
||||
|
||||
switch (selectedStoredIndex) {
|
||||
case 0:
|
||||
return MPSiteTypeStoredPersonal;
|
||||
return MPResultTypeStatefulPersonal;
|
||||
case 1:
|
||||
return MPSiteTypeStoredDevicePrivate;
|
||||
return MPResultTypeStatefulDevice;
|
||||
default:
|
||||
Throw( @"unsupported selected type index: generated1=%ld, generated2=%ld, stored=%ld",
|
||||
(long)selectedGenerated1Index, (long)selectedGenerated2Index, (long)selectedStoredIndex );
|
||||
@@ -282,44 +282,44 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)generated1SegmentIndexForType:(MPSiteType)type {
|
||||
- (NSInteger)generated1SegmentIndexForType:(MPResultType)type {
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedPhrase:
|
||||
case MPResultTypeTemplatePhrase:
|
||||
return 0;
|
||||
case MPSiteTypeGeneratedName:
|
||||
case MPResultTypeTemplateName:
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)generated2SegmentIndexForType:(MPSiteType)type {
|
||||
- (NSInteger)generated2SegmentIndexForType:(MPResultType)type {
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum:
|
||||
case MPResultTypeTemplateMaximum:
|
||||
return 0;
|
||||
case MPSiteTypeGeneratedLong:
|
||||
case MPResultTypeTemplateLong:
|
||||
return 1;
|
||||
case MPSiteTypeGeneratedMedium:
|
||||
case MPResultTypeTemplateMedium:
|
||||
return 2;
|
||||
case MPSiteTypeGeneratedBasic:
|
||||
case MPResultTypeTemplateBasic:
|
||||
return 3;
|
||||
case MPSiteTypeGeneratedShort:
|
||||
case MPResultTypeTemplateShort:
|
||||
return 4;
|
||||
case MPSiteTypeGeneratedPIN:
|
||||
case MPResultTypeTemplatePIN:
|
||||
return 5;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)storedSegmentIndexForType:(MPSiteType)type {
|
||||
- (NSInteger)storedSegmentIndexForType:(MPResultType)type {
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeStoredPersonal:
|
||||
case MPResultTypeStatefulPersonal:
|
||||
return 0;
|
||||
case MPSiteTypeStoredDevicePrivate:
|
||||
case MPResultTypeStatefulDevice:
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
[PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
|
||||
initSheet:^(UIActionSheet *sheet) {
|
||||
for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) {
|
||||
MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue];
|
||||
MPResultType type = (MPResultType)[typeNumber unsignedIntegerValue];
|
||||
NSString *typeName = [mainSite.algorithm nameOfType:type];
|
||||
if (type == mainSite.type)
|
||||
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
|
||||
@@ -295,7 +295,7 @@
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
MPSiteType type = (MPSiteType)[[mainSite.algorithm allTypes][buttonIndex] unsignedIntegerValue]?:
|
||||
MPResultType type = (MPResultType)[[mainSite.algorithm allTypes][buttonIndex] unsignedIntegerValue]?:
|
||||
mainSite.user.defaultType?: mainSite.algorithm.defaultType;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
@@ -311,7 +311,7 @@
|
||||
self.loginNameField.enabled = YES;
|
||||
self.passwordField.enabled = YES;
|
||||
|
||||
if ([self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].type & MPSiteTypeClassStored)
|
||||
if ([self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].type & MPResultTypeClassStateful)
|
||||
[self.passwordField becomeFirstResponder];
|
||||
else
|
||||
[self.loginNameField becomeFirstResponder];
|
||||
@@ -537,7 +537,7 @@
|
||||
self.loginNameContainer.visible = settingsMode || mainSite.loginGenerated || [mainSite.loginName length];
|
||||
self.modeButton.visible = !self.transientSite;
|
||||
self.modeButton.alpha = settingsMode? 0.5f: 0.1f;
|
||||
self.counterLabel.visible = self.counterButton.visible = mainSite.type & MPSiteTypeClassGenerated;
|
||||
self.counterLabel.visible = self.counterButton.visible = mainSite.type & MPResultTypeClassTemplate;
|
||||
self.modeButton.selected = settingsMode;
|
||||
self.strengthLabel.gone = !settingsMode;
|
||||
self.modeScrollView.scrollEnabled = !self.transientSite;
|
||||
@@ -565,8 +565,8 @@
|
||||
// Site Password
|
||||
self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
|
||||
self.passwordField.attributedPlaceholder = stra(
|
||||
mainSite.type & MPSiteTypeClassStored? strl( @"No password" ):
|
||||
mainSite.type & MPSiteTypeClassGenerated? strl( @"..." ): @"", @{
|
||||
mainSite.type & MPResultTypeClassStateful? strl( @"No password" ):
|
||||
mainSite.type & MPResultTypeClassTemplate? strl( @"..." ): @"", @{
|
||||
NSForegroundColorAttributeName: [UIColor whiteColor]
|
||||
} );
|
||||
|
||||
@@ -585,9 +585,9 @@
|
||||
|
||||
BOOL loginGenerated = site.loginGenerated;
|
||||
NSString *password = nil, *loginName = [site resolveLoginUsingKey:key];
|
||||
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPAlgorithmDefault.defaultType;
|
||||
if (self.transientSite && transientType & MPSiteTypeClassGenerated)
|
||||
password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:transientType
|
||||
MPResultType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPAlgorithmDefault.defaultType;
|
||||
if (self.transientSite && transientType & MPResultTypeClassTemplate)
|
||||
password = [MPAlgorithmDefault mpwTemplateForSiteNamed:self.transientSite ofType:transientType
|
||||
withCounter:1 usingKey:key];
|
||||
else if (site)
|
||||
password = [site resolvePasswordUsingKey:key];
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
@protocol MPTypeDelegate<NSObject>
|
||||
|
||||
@required
|
||||
- (void)didSelectType:(MPSiteType)type;
|
||||
- (MPSiteType)selectedType;
|
||||
- (void)didSelectType:(MPResultType)type;
|
||||
- (MPResultType)selectedType;
|
||||
|
||||
@optional
|
||||
- (MPSiteEntity *)selectedSite;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
@interface MPTypeViewController()
|
||||
|
||||
- (MPSiteType)typeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
- (MPResultType)typeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
@end
|
||||
|
||||
@@ -75,20 +75,20 @@
|
||||
if ([self.delegate respondsToSelector:@selector( selectedSite )])
|
||||
selectedSite = [self.delegate selectedSite];
|
||||
|
||||
MPSiteType cellType = [self typeAtIndexPath:indexPath];
|
||||
MPSiteType selectedType = selectedSite? selectedSite.type: [self.delegate selectedType];
|
||||
MPResultType cellType = [self typeAtIndexPath:indexPath];
|
||||
MPResultType selectedType = selectedSite? selectedSite.type: [self.delegate selectedType];
|
||||
cell.selected = (selectedType == cellType);
|
||||
|
||||
if (cellType != (MPSiteType)NSNotFound && cellType & MPSiteTypeClassGenerated) {
|
||||
if (cellType != (MPResultType)NSNotFound && cellType & MPResultTypeClassTemplate) {
|
||||
[(UITextField *)[cell viewWithTag:2] setText:@"..."];
|
||||
|
||||
NSString *name = selectedSite.name;
|
||||
NSUInteger counter = 0;
|
||||
MPCounterValue counter = 0;
|
||||
if ([selectedSite isKindOfClass:[MPGeneratedSiteEntity class]])
|
||||
counter = ((MPGeneratedSiteEntity *)selectedSite).counter;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
NSString *typeContent = [MPAlgorithmDefault generatePasswordForSiteNamed:name ofType:cellType
|
||||
NSString *typeContent = [MPAlgorithmDefault mpwTemplateForSiteNamed:name ofType:cellType
|
||||
withCounter:counter usingKey:[MPiOSAppDelegate get].key];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
@@ -104,8 +104,8 @@
|
||||
|
||||
NSAssert( self.navigationController.topViewController == self, @"Not the currently active navigation item." );
|
||||
|
||||
MPSiteType type = [self typeAtIndexPath:indexPath];
|
||||
if (type == (MPSiteType)NSNotFound)
|
||||
MPResultType type = [self typeAtIndexPath:indexPath];
|
||||
if (type == (MPResultType)NSNotFound)
|
||||
// Selected a non-type row.
|
||||
return;
|
||||
|
||||
@@ -113,28 +113,28 @@
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (MPSiteType)typeAtIndexPath:(NSIndexPath *)indexPath {
|
||||
- (MPResultType)typeAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
switch (indexPath.section) {
|
||||
case 0: {
|
||||
// Generated
|
||||
switch (indexPath.row) {
|
||||
case 0:
|
||||
return (MPSiteType)NSNotFound;
|
||||
return (MPResultType)NSNotFound;
|
||||
case 1:
|
||||
return MPSiteTypeGeneratedMaximum;
|
||||
return MPResultTypeTemplateMaximum;
|
||||
case 2:
|
||||
return MPSiteTypeGeneratedLong;
|
||||
return MPResultTypeTemplateLong;
|
||||
case 3:
|
||||
return MPSiteTypeGeneratedMedium;
|
||||
return MPResultTypeTemplateMedium;
|
||||
case 4:
|
||||
return MPSiteTypeGeneratedBasic;
|
||||
return MPResultTypeTemplateBasic;
|
||||
case 5:
|
||||
return MPSiteTypeGeneratedShort;
|
||||
return MPResultTypeTemplateShort;
|
||||
case 6:
|
||||
return MPSiteTypeGeneratedPIN;
|
||||
return MPResultTypeTemplatePIN;
|
||||
case 7:
|
||||
return (MPSiteType)NSNotFound;
|
||||
return (MPResultType)NSNotFound;
|
||||
|
||||
default: {
|
||||
Throw( @"Unsupported row: %ld, when selecting generated site type.", (long)indexPath.row );
|
||||
@@ -146,13 +146,13 @@
|
||||
// Stored
|
||||
switch (indexPath.row) {
|
||||
case 0:
|
||||
return (MPSiteType)NSNotFound;
|
||||
return (MPResultType)NSNotFound;
|
||||
case 1:
|
||||
return MPSiteTypeStoredPersonal;
|
||||
return MPResultTypeStatefulPersonal;
|
||||
case 2:
|
||||
return MPSiteTypeStoredDevicePrivate;
|
||||
return MPResultTypeStatefulDevice;
|
||||
case 3:
|
||||
return (MPSiteType)NSNotFound;
|
||||
return (MPResultType)NSNotFound;
|
||||
|
||||
default: {
|
||||
Throw( @"Unsupported row: %ld, when selecting stored site type.", (long)indexPath.row );
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPStoreViewController.h"
|
||||
#import "mpw-marshall.h"
|
||||
|
||||
@interface MPiOSAppDelegate()<UIDocumentInteractionControllerDelegate>
|
||||
|
||||
@@ -177,62 +178,46 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)importSites:(NSString *)importedSitesString {
|
||||
- (void)importSites:(NSString *)importData {
|
||||
|
||||
if ([NSThread isMainThread]) {
|
||||
PearlNotMainQueue( ^{
|
||||
[self importSites:importedSitesString];
|
||||
[self importSites:importData];
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
PearlOverlay *activityOverlay = [PearlOverlay showProgressOverlayWithTitle:@"Importing"];
|
||||
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
||||
[self importSites:importData askImportPassword:^NSString *(NSString *userName) {
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
|
||||
message:strf( @"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName )
|
||||
[PearlAlert showAlertWithTitle:strf( @"Importing Sites For\n%@", userName )
|
||||
message:@"Enter the master password used to create this export file."
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
setResult( nil );
|
||||
else
|
||||
setResult( [alert_ textFieldAtIndex:0].text );
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock Import", nil];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil];
|
||||
} );
|
||||
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
|
||||
} askUserPassword:^NSString *(NSString *userName) {
|
||||
return PearlAwait( (id)^(void (^setResult)(id)) {
|
||||
[PearlAlert showAlertWithTitle:strf( @"Master Password for\n%@", userName )
|
||||
message:strf( @"Imports %lu sites, overwriting %lu.",
|
||||
(unsigned long)importCount, (unsigned long)deleteCount )
|
||||
[PearlAlert showAlertWithTitle:strf( @"Master Password For\n%@", userName )
|
||||
message:@"Enter the current master password for this user."
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
setResult( nil );
|
||||
else
|
||||
setResult( [alert_ textFieldAtIndex:0].text );
|
||||
}
|
||||
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil];
|
||||
} );
|
||||
}];
|
||||
|
||||
switch (result) {
|
||||
case MPImportResultSuccess:
|
||||
case MPImportResultCancelled:
|
||||
break;
|
||||
case MPImportResultInternalError:
|
||||
[PearlAlert showError:@"Import failed because of an internal error."];
|
||||
break;
|
||||
case MPImportResultMalformedInput:
|
||||
[PearlAlert showError:@"The import doesn't look like a Master Password export."];
|
||||
break;
|
||||
case MPImportResultInvalidPassword:
|
||||
[PearlAlert showError:@"Incorrect master password for the import sites."];
|
||||
break;
|
||||
}
|
||||
|
||||
} result:^(NSError *error) {
|
||||
[activityOverlay cancelOverlayAnimated:YES];
|
||||
|
||||
if (error && !(error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError))
|
||||
[PearlAlert showError:error.localizedDescription];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
@@ -250,10 +235,9 @@
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:nil];
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
NSString *importHeader = @"# Master Password site export";
|
||||
NSString *importedSitesString = [UIPasteboard generalPasteboard].string;
|
||||
if ([importedSitesString length] > [importHeader length] &&
|
||||
[[importedSitesString substringToIndex:[importHeader length]] isEqualToString:importHeader])
|
||||
NSString *importData = [UIPasteboard generalPasteboard].string;
|
||||
MPMarshallInfo *importInfo = mpw_marshall_read_info( importData.UTF8String );
|
||||
if (importInfo->format != MPMarshallFormatNone)
|
||||
[PearlAlert showAlertWithTitle:@"Import Sites?" message:
|
||||
@"We've detected Master Password import sites on your pasteboard, would you like to import them?"
|
||||
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||
@@ -261,9 +245,10 @@
|
||||
if (buttonIndex == [alert cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[self importSites:importedSitesString];
|
||||
[self importSites:importData];
|
||||
[UIPasteboard generalPasteboard].string = @"";
|
||||
} cancelTitle:@"No" otherTitles:@"Import Sites", nil];
|
||||
mpw_marshal_info_free( &importInfo );
|
||||
} );
|
||||
|
||||
[super applicationDidBecomeActive:application];
|
||||
@@ -449,9 +434,41 @@
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords];
|
||||
NSString *message;
|
||||
[self exportSitesRevealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) {
|
||||
return PearlAwait( ^(void (^setResult)(id)) {
|
||||
[PearlAlert showAlertWithTitle:strf( @"Master Password For:\n%@", userName )
|
||||
message:@"Enter the user's master password to create an export file."
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
if (buttonIndex_ == [alert_ cancelButtonIndex])
|
||||
setResult( nil );
|
||||
else
|
||||
setResult( [alert_ textFieldAtIndex:0].text );
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Export", nil];
|
||||
} );
|
||||
} result:^(NSString *mpsites, NSError *error) {
|
||||
if (!mpsites || error) {
|
||||
MPError( error, @"Failed to export mpsites." );
|
||||
[PearlAlert showAlertWithTitle:@"Export Error"
|
||||
message:error.localizedDescription
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:nil cancelTitle:[PearlStrings get].commonButtonOkay
|
||||
otherTitles:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
[PearlSheet showSheetWithTitle:@"Export Destination" viewStyle:UIActionSheetStyleBlackTranslucent initSheet:nil
|
||||
tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||
NSString *exportFileName = strf( @"%@ (%@).mpsites",
|
||||
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] );
|
||||
|
||||
if (buttonIndex == [sheet firstOtherButtonIndex]) {
|
||||
NSString *message;
|
||||
if (revealPasswords)
|
||||
message = strf( @"Export of Master Password sites with passwords included.\n\n"
|
||||
@"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n"
|
||||
@@ -470,20 +487,9 @@
|
||||
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||
[PearlInfoPlist get].CFBundleVersion );
|
||||
|
||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||
|
||||
NSString *exportFileName = strf( @"%@ (%@).mpsites",
|
||||
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] );
|
||||
[PearlSheet showSheetWithTitle:@"Export Destination" viewStyle:UIActionSheetStyleBlackTranslucent initSheet:nil
|
||||
tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
if (buttonIndex == [sheet firstOtherButtonIndex]) {
|
||||
[PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message
|
||||
attachments:[[PearlEMailAttachment alloc]
|
||||
initWithContent:[exportedSites dataUsingEncoding:NSUTF8StringEncoding]
|
||||
initWithContent:[mpsites dataUsingEncoding:NSUTF8StringEncoding]
|
||||
mimeType:@"text/plain" fileName:exportFileName],
|
||||
nil];
|
||||
return;
|
||||
@@ -494,10 +500,10 @@
|
||||
NSURL *exportURL = [[applicationSupportURL
|
||||
URLByAppendingPathComponent:[NSBundle mainBundle].bundleIdentifier isDirectory:YES]
|
||||
URLByAppendingPathComponent:exportFileName isDirectory:NO];
|
||||
NSError *error = nil;
|
||||
if (![[exportedSites dataUsingEncoding:NSUTF8StringEncoding]
|
||||
writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&error])
|
||||
MPError( error, @"Failed to write export data to URL %@.", exportURL );
|
||||
NSError *writeError = nil;
|
||||
if (![[mpsites dataUsingEncoding:NSUTF8StringEncoding]
|
||||
writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&writeError])
|
||||
MPError( writeError, @"Failed to write export data to URL %@.", exportURL );
|
||||
else {
|
||||
self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:exportURL];
|
||||
self.interactionController.UTI = @"com.lyndir.masterpassword.sites";
|
||||
@@ -505,6 +511,7 @@
|
||||
[self.interactionController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES];
|
||||
}
|
||||
} cancelTitle:@"Cancel" destructiveTitle:nil otherTitles:@"Send As E-Mail", @"Share / Airdrop", nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset {
|
||||
|
||||
11
platform-independent/cli-c/.gitignore
vendored
Normal file
11
platform-independent/cli-c/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
*.o
|
||||
*.dSYM
|
||||
|
||||
mpw
|
||||
mpw-bench
|
||||
mpw-tests
|
||||
|
||||
TAG
|
||||
VERSION
|
||||
mpw-*.tar.gz
|
||||
mpw-*.tar.gz.sig
|
||||
84
platform-independent/cli-c/README.md
Normal file
84
platform-independent/cli-c/README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Native CLI
|
||||
|
||||
This is a command-line terminal interface to the Master Password standard implementation.
|
||||
|
||||
To use the app, you'll first need to build it, then install it into your system's PATH.
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
To build the code to run on your specific system, run the `build` command:
|
||||
|
||||
./build
|
||||
|
||||
Note that the build depends on your system having certain dependencies already installed.
|
||||
By default, you'll need to have at least `libsodium`, `libjson-c` and `libncurses` installed.
|
||||
|
||||
|
||||
### Details
|
||||
|
||||
The build script comes with a default configuration which can be adjusted. Full details on the build script are available by opening the build script file.
|
||||
|
||||
[targets='...'] [mpw_feature=0|1 ...] [CFLAGS='...'] [LDFLAGS='...'] ./build [cc arguments ...]
|
||||
|
||||
By default, the build script only builds the `mpw` target. You can specify other targets or `all` to build all available targets. These are the currently available targets:
|
||||
|
||||
- `mpw` : The main app. It needs: `mpw_sodium`, optionally supports: `mpw_color`, `mpw_json`.
|
||||
- `mpw-bench` : A benchmark utility. It needs: `mpw_sodium`.
|
||||
- `mpw-tests` : An algorithm test suite. It needs: `mpw_sodium`, `mpw_xml`.
|
||||
|
||||
It is smart to build the test suite along with the app, eg.:
|
||||
|
||||
targets='mpw mpw-tests' ./build
|
||||
|
||||
The needed and supported features determine the dependencies that the build will require. The following features exist:
|
||||
|
||||
- `mpw_sodium` : Use Sodium for the crypto implementation. It needs libsodium.
|
||||
- `mpw_json` : Support JSON-based user configuration format. It needs libjson-c.
|
||||
- `mpw_color` : Show a colorized identicon. It needs libncurses.
|
||||
- `mpw_xml` : Support XML parsing. It needs libxml2.
|
||||
|
||||
By default, all features are enabled. Each feature can be disabled or enabled explicitly by prefixing the build command with an assignment of it to `0` or `1`, eg.:
|
||||
|
||||
mpw_color=0 ./build
|
||||
|
||||
As a result of this command, you'd build the `mpw` target (which supports `mpw_color`) without color support. The build no longer requires `libncurses` but the resulting `mpw` binary will not have support for colorized identicons.
|
||||
|
||||
You can also pass CFLAGS or LDFLAGS to the build, or extra custom compiler arguments as arguments to the build script.
|
||||
For instance, to add a custom library search path, you could use:
|
||||
|
||||
LDFLAGS='-L/usr/local/lib' ./build
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
Once the client is built, you should run a test suite to make sure everything works as intended.
|
||||
|
||||
There are currently two test suites:
|
||||
|
||||
- `mpw-tests` : Tests the Master Password algorithm implementation.
|
||||
- `mpw-cli-tests` : Tests the CLI application.
|
||||
|
||||
The `mpw-tests` suite is only available if you enabled its target during build (see "Details" above).
|
||||
|
||||
The `mpw-cli-tests` is a Bash shell script, hence depends on your system having Bash available.
|
||||
|
||||
|
||||
## Installing
|
||||
|
||||
Once you're happy with the result, you can install the `mpw` application into your system's `PATH`.
|
||||
|
||||
Generally, all you need to do is copy the `mpw` file into a PATH directory, eg.:
|
||||
|
||||
cp mpw /usr/local/bin/
|
||||
|
||||
The directory that you should copy the `mpw` file into will depend on your system. Also note that `cp` is a POSIX command, if your system is not a POSIX system (eg. Windows) you'll need to adjust accordingly.
|
||||
|
||||
There is also an `install` script to help with this process, though it is a Bash script and therefore requires that you have Bash installed:
|
||||
|
||||
./install
|
||||
|
||||
After installing, you should be able to run `mpw` and use it from anywhere in the terminal:
|
||||
|
||||
mpw -h
|
||||
mpw google.com
|
||||
@@ -1,16 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# TROUBLESHOOTING
|
||||
# - If you see 'undefined reference to `AES_encrypt'',
|
||||
# make sure you have openssl installed.
|
||||
# If libcrypto.a is in a non-standard directory, try ./build -L[your-lib-dir]
|
||||
# - If you see 'undefined reference to `clock_gettime'',
|
||||
# try ./build -lrt instead.
|
||||
# - If you see 'x86.S:202: Error: junk at end of line, first unrecognized character is `,'',
|
||||
# try commenting the line in lib/bcrypt/x86.S.
|
||||
# - Take a look at the "Optional features" section. Some features have dependencies,
|
||||
# either make sure you have them or disable those features.
|
||||
# eg. mpw_color=0 ./build
|
||||
# USAGE
|
||||
# [targets='...'] [mpw_feature=0|1 ...] [CFLAGS='...'] [LDFLAGS='...'] ./build [cc arguments ...]
|
||||
#
|
||||
# By default, you should only need to run ./build
|
||||
#
|
||||
# You can customize the targets that are built using targets='...'. Use targets='all' to build all targets.
|
||||
# By default, we only build the 'mpw' target.
|
||||
# See targets_all for all possible targets as well as the features they support and require.
|
||||
#
|
||||
# Several features can be enabled or disabled using feature flags.
|
||||
# See the Features section for an overview of the features, their default setting, their meaning and their dependencies.
|
||||
# You will need to have each of the feature's dependencies installed for the build to succeed with that feature enabled.
|
||||
#
|
||||
# Finally, the C compiler can be tuned using CFLAGS, LDFLAGS and compiler arguments passed to the script.
|
||||
#
|
||||
# BUGS
|
||||
# masterpassword@lyndir.com
|
||||
@@ -24,333 +27,110 @@ set -e
|
||||
|
||||
|
||||
### CONFIGURATION
|
||||
|
||||
# Targets to build.
|
||||
if [[ $targets ]]; then
|
||||
read -ra targets <<< "$targets"
|
||||
else
|
||||
# Default targets.
|
||||
# Modify here or override using targets='mpw mpw-bench' ./build
|
||||
targets=(
|
||||
mpw # C CLI version of Master Password, requires libsodium or openssl-dev.
|
||||
#mpw-bench # C CLI Master Password benchmark utility.
|
||||
#mpw-tests # C Master Password algorithm test suite, requires libxml2.
|
||||
targets_all=(
|
||||
mpw # C CLI version of Master Password (needs: mpw_sodium, optional: mpw_color, mpw_json).
|
||||
mpw-bench # C CLI Master Password benchmark utility (needs: mpw_sodium).
|
||||
mpw-tests # C Master Password algorithm test suite (needs: mpw_sodium, mpw_xml).
|
||||
)
|
||||
fi
|
||||
targets_default='mpw' # Override with: targets='...' ./build
|
||||
|
||||
# Optional features.
|
||||
mpw_color=${mpw_color:-1} # Colorized Identicon, requires libncurses-dev.
|
||||
mpw_json=${mpw_json:-1} # Support for JSON-based user configuration format.
|
||||
mpw_sodium=${mpw_sodium:-1} # Use libsodium if available instead of cperciva's libscrypt.
|
||||
# Features.
|
||||
mpw_sodium=${mpw_sodium:-1} # Implement crypto functions with sodium (depends on libsodium).
|
||||
mpw_json=${mpw_json:-1} # Support JSON-based user configuration format (depends on libjson-c).
|
||||
mpw_color=${mpw_color:-1} # Colorized identicon (depends on libncurses).
|
||||
mpw_xml=${mpw_xml:-1} # XML parsing (depends on libxml2).
|
||||
|
||||
# Default build flags.
|
||||
export CFLAGS="-O3 $CFLAGS"
|
||||
export LDFLAGS="$LDFLAGS"
|
||||
cflags=( -O3 $CFLAGS )
|
||||
ldflags=( $LDFLAGS )
|
||||
|
||||
# Version.
|
||||
if { mpw_version=$(git describe --match '*-cli*' --long --dirty --broken) || mpw_version=$(<VERSION); } 2>/dev/null; then
|
||||
CFLAGS+=" -DMP_VERSION=$mpw_version"
|
||||
cflags+=( -D"MP_VERSION=$mpw_version" )
|
||||
fi
|
||||
echo 2>&1 "Building mpw version ${mpw_version:-<unknown>}..."
|
||||
|
||||
# Distribution specific configuration.
|
||||
# Homebrew - openssl for scrypt
|
||||
if hash brew 2>/dev/null; then
|
||||
opensslPath=$(brew --prefix openssl)
|
||||
CFLAGS+=" -I$opensslPath/include"
|
||||
LDFLAGS+=" -L$opensslPath/lib"
|
||||
fi
|
||||
|
||||
### DEPENDENCIES
|
||||
|
||||
digest() {
|
||||
openssl sha -sha256 -binary < "$1" | od -t x1 -An -v | tr -d '[:space:]'
|
||||
}
|
||||
fetch() {
|
||||
if hash wget 2>/dev/null; then
|
||||
wget -O "${1##*/}" "$1"
|
||||
elif hash curl 2>/dev/null; then
|
||||
curl "$1" > "${1##*/}"
|
||||
fi
|
||||
}
|
||||
unpack() {
|
||||
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
||||
[[ $(digest "$1") = $2 ]] || {
|
||||
printf ' mismatch!\n'
|
||||
echo 2>&1 "Downloaded package doesn't match digest."
|
||||
exit 1
|
||||
}
|
||||
printf ' OK!\n'
|
||||
|
||||
if [[ $1 = *.tar.gz || $1 = *.tgz ]]; then
|
||||
tar -xvzf "$1"
|
||||
|
||||
elif [[ $1 = *.tar.bz2 || $1 = *.tbz2 ]]; then
|
||||
tar -xvjf "$1"
|
||||
|
||||
elif [[ $1 = *.tar ]]; then
|
||||
tar -xvf "$1"
|
||||
|
||||
else
|
||||
echo 2>&1 "Don't know how to unpack: $1"
|
||||
fi
|
||||
|
||||
files=( * )
|
||||
if [[ -d $files ]] && (( ${#files[@]} == 1 )); then
|
||||
mv "$files"/* .
|
||||
rmdir "$files"
|
||||
fi
|
||||
}
|
||||
fetchSource() (
|
||||
local name=${PWD##*/}
|
||||
source .source
|
||||
|
||||
if [[ -e .unpacked ]]; then
|
||||
true
|
||||
|
||||
elif [[ $pkg && -e "${pkg##*/}" ]]; then
|
||||
[[ -e src ]] || {
|
||||
echo
|
||||
echo "Unpacking: $name, using package..."
|
||||
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $git ]] && hash git 2>/dev/null; then
|
||||
[[ -e .git ]] || {
|
||||
echo
|
||||
echo "Fetching: $name, using git..."
|
||||
git clone "$git" src
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $svn ]] && hash git 2>/dev/null && [[ -x "$(git --exec-path)/git-svn" ]]; then
|
||||
[[ -e .git ]] || {
|
||||
echo
|
||||
echo "Fetching: $name, using git-svn..."
|
||||
git svn clone --prefix=origin/ --stdlayout "$svn" src
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $svn ]] && hash svn 2>/dev/null; then
|
||||
[[ -e .svn ]] || {
|
||||
echo
|
||||
echo "Fetching: $name, using svn..."
|
||||
svn checkout "$svn/trunk" src
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $pkg ]]; then
|
||||
[[ -e src ]] || {
|
||||
echo
|
||||
echo "Fetching: $name, using package..."
|
||||
fetch "$pkg"
|
||||
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
else
|
||||
echo >&2 "error: Missing git-svn or svn."
|
||||
echo >&2 "error: Please install either or manually check out the sources"
|
||||
echo >&2 "error: from: $home"
|
||||
echo >&2 "error: into: $PWD/src"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -e .patched ]] && (( ${#patches[@]} )); then
|
||||
pushd src
|
||||
for patch in "${patches[@]}"; do
|
||||
echo
|
||||
echo "Patching: $name, for $patch..."
|
||||
patch -p0 < "../$patch.patch"
|
||||
done
|
||||
popd
|
||||
touch .patched
|
||||
fi
|
||||
)
|
||||
depend() {
|
||||
local name=$1
|
||||
|
||||
echo
|
||||
echo "Checking dependency: $name..."
|
||||
[[ -e "lib/include/$name" ]] && return
|
||||
|
||||
pushd "lib/$name"
|
||||
fetchSource
|
||||
pushd "src"
|
||||
|
||||
echo
|
||||
echo "Configuring dependency: $name..."
|
||||
if [[ -e configure.ac ]]; then
|
||||
if [[ ! -e configure ]]; then
|
||||
# create configure using autotools.
|
||||
if ! hash aclocal || ! hash automake; then
|
||||
echo >&2 "Need autotools to build $name. Please install automake and autoconf."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
aclocal
|
||||
autoheader
|
||||
autoconf
|
||||
mkdir -p config.aux
|
||||
automake --add-missing
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -e configure ]]; then
|
||||
./configure
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Building dependency: $name..."
|
||||
if [[ -e Makefile ]]; then
|
||||
if ! hash make; then
|
||||
echo >&2 "Need make to build $name. Please install GNU make."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make
|
||||
install -d "../../include/$name/"
|
||||
find . -name '*.h' -exec install -m 444 {} "../../include/$name/" \;
|
||||
else
|
||||
echo >&2 "error: Don't know how to build: $name"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
popd
|
||||
}
|
||||
depend_scrypt() {
|
||||
if (( mpw_sodium )) && haslib sodium; then
|
||||
if [[ $CFLAGS != *HAS_SODIUM=1* ]]; then
|
||||
CFLAGS+=" -DHAS_SODIUM=1"
|
||||
LDFLAGS+=" -lsodium"
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
depend scrypt
|
||||
if [[ $CFLAGS != *HAS_CPERCIVA=1* ]]; then
|
||||
local objects=(
|
||||
"lib/scrypt/src/libcperciva/"*/*.o
|
||||
"lib/scrypt/src/lib/crypto/"*.o
|
||||
)
|
||||
CFLAGS+=" -DHAS_CPERCIVA=1"
|
||||
LDFLAGS+=" -Llib/scrypt/src ${objects[*]}"
|
||||
fi
|
||||
}
|
||||
echo 2>&1 "Current mpw source version ${mpw_version:-<unknown>}..."
|
||||
|
||||
|
||||
### MPW
|
||||
### TARGET: MPW
|
||||
mpw() {
|
||||
depend_scrypt
|
||||
# dependencies
|
||||
use_mpw_sodium
|
||||
use_mpw_color
|
||||
use_mpw_json
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
local CFLAGS=(
|
||||
$CFLAGS
|
||||
# target
|
||||
cflags=(
|
||||
"${cflags[@]}"
|
||||
|
||||
# library paths
|
||||
-I"lib/include"
|
||||
# mpw paths
|
||||
-I"core" -I"cli"
|
||||
)
|
||||
local LDFLAGS=(
|
||||
$LDFLAGS
|
||||
|
||||
# link libraries
|
||||
-l"crypto"
|
||||
ldflags=(
|
||||
"${ldflags[@]}"
|
||||
)
|
||||
# optional features
|
||||
(( mpw_color )) && CFLAGS+=( -DMPW_COLOR ) LDFLAGS+=( -l"curses" )
|
||||
(( mpw_json )) && CFLAGS+=( -DMPW_JSON ) LDFLAGS+=( -l"json-c" )
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/base64.c -o core/base64.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-marshall-util.c -o core/mpw-marshall-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-marshall.c -o core/mpw-marshall.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/base64.o" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" "core/mpw-marshall-util.o" "core/mpw-marshall.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-cli.c" -o "mpw"
|
||||
echo "done! Now run ./install or use ./mpw"
|
||||
# build
|
||||
cc "${cflags[@]}" "$@" "core/base64.c" "core/mpw-algorithm.c" "core/mpw-types.c" "core/mpw-util.c" "core/mpw-marshall-util.c" "core/mpw-marshall.c" "cli/mpw-cli-util.c" \
|
||||
"${ldflags[@]}" "cli/mpw-cli.c" -o "mpw"
|
||||
echo "done! You can now run ./mpw-cli-tests, ./install or use ./$_"
|
||||
}
|
||||
|
||||
|
||||
### MPW-BENCH
|
||||
### TARGET: MPW-BENCH
|
||||
mpw-bench() {
|
||||
depend_scrypt
|
||||
depend bcrypt
|
||||
# dependencies
|
||||
use_mpw_sodium
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
local CFLAGS=(
|
||||
$CFLAGS
|
||||
# target
|
||||
cflags=(
|
||||
"${cflags[@]}"
|
||||
|
||||
# library paths
|
||||
-I"lib/include"
|
||||
# mpw paths
|
||||
-I"core" -I"cli"
|
||||
)
|
||||
local LDFLAGS=(
|
||||
$LDFLAGS
|
||||
|
||||
# bcrypt
|
||||
"lib/bcrypt/src/crypt_blowfish.o"
|
||||
"lib/bcrypt/src/crypt_gensalt.o"
|
||||
"lib/bcrypt/src/wrapper.o"
|
||||
"lib/bcrypt/src/x86.o"
|
||||
# library paths
|
||||
-L"lib/bcrypt/src"
|
||||
# link libraries
|
||||
-l"crypto"
|
||||
ldflags=(
|
||||
"${ldflags[@]}"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/base64.c -o core/base64.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/base64.o" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-bench.c" -o "mpw-bench"
|
||||
echo "done! Now use ./mpw-bench"
|
||||
# build
|
||||
cc "${cflags[@]}" "$@" "core/base64.c" "core/mpw-algorithm.c" "core/mpw-types.c" "core/mpw-util.c" \
|
||||
"${ldflags[@]}" "cli/mpw-bench.c" -o "mpw-bench"
|
||||
echo "done! You can now use ./$_"
|
||||
}
|
||||
|
||||
|
||||
### MPW-TESTS
|
||||
### TARGET: MPW-TESTS
|
||||
mpw-tests() {
|
||||
depend_scrypt
|
||||
# dependencies
|
||||
use_mpw_xml
|
||||
use_mpw_sodium
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
local CFLAGS=(
|
||||
$CFLAGS
|
||||
# target
|
||||
cflags=(
|
||||
"${cflags[@]}"
|
||||
|
||||
# library paths
|
||||
-I"lib/include"
|
||||
-I"/usr/include/libxml2"
|
||||
-I"/usr/local/include/libxml2"
|
||||
# mpw paths
|
||||
-I"core" -I"cli"
|
||||
)
|
||||
local LDFLAGS=(
|
||||
$LDFLAGS
|
||||
|
||||
# link libraries
|
||||
-l"crypto" -l"xml2"
|
||||
ldflags=(
|
||||
"${ldflags[@]}"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/base64.c -o core/base64.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c cli/mpw-tests-util.c -o cli/mpw-tests-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/base64.o" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-tests-util.o" "cli/mpw-tests.c" -o "mpw-tests"
|
||||
echo "done! Now use ./mpw-tests"
|
||||
# build
|
||||
cc "${cflags[@]}" "$@" "core/base64.c" "core/mpw-algorithm.c" "core/mpw-types.c" "core/mpw-util.c" "cli/mpw-tests-util.c" \
|
||||
"${ldflags[@]}" "cli/mpw-tests.c" -o "mpw-tests"
|
||||
echo "done! You can now use ./$_"
|
||||
}
|
||||
|
||||
|
||||
### TARGETS
|
||||
|
||||
### TOOLS
|
||||
haslib() {
|
||||
cc -l"$1" -x c -o /dev/null - <<< 'int main() { return 0; }'
|
||||
}
|
||||
@@ -367,7 +147,59 @@ cc() {
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Will build targets: ${targets[*]}..."
|
||||
for target in "${targets[@]}"; do
|
||||
"$target" "$@"
|
||||
|
||||
### DEPENDENCIES
|
||||
use_mpw_sodium() {
|
||||
! (( mpw_sodium )) && return
|
||||
|
||||
if ! haslib sodium; then
|
||||
echo >&2 "WARNING: mpw_sodium enabled but missing sodium library, will disable mpw_sodium."
|
||||
|
||||
else
|
||||
echo >&2 "Enabled mpw_sodium (libsodium)."
|
||||
cflags+=( -D"MPW_SODIUM=1" ) ldflags+=( -l"sodium" )
|
||||
fi
|
||||
}
|
||||
use_mpw_color() {
|
||||
! (( mpw_color )) && return
|
||||
|
||||
if ! haslib curses; then
|
||||
echo >&2 "WARNING: mpw_color enabled but missing curses library, will disable mpw_color."
|
||||
|
||||
else
|
||||
echo >&2 "Enabled mpw_color (libcurses)."
|
||||
cflags+=( -D"MPW_COLOR=1" ) ldflags+=( -l"curses" )
|
||||
fi
|
||||
}
|
||||
use_mpw_json() {
|
||||
! (( mpw_json )) && return
|
||||
|
||||
if ! haslib json-c; then
|
||||
echo >&2 "WARNING: mpw_json enabled but missing json-c library, will disable mpw_json."
|
||||
|
||||
else
|
||||
echo >&2 "Enabled mpw_json (libjson-c)."
|
||||
cflags+=( -D"MPW_JSON=1" ) ldflags+=( -l"json-c" )
|
||||
fi
|
||||
}
|
||||
use_mpw_xml() {
|
||||
! (( mpw_xml )) && return
|
||||
|
||||
if ! haslib xml2; then
|
||||
echo >&2 "WARNING: mpw_xml enabled but missing xml2 library, will disable mpw_xml."
|
||||
|
||||
else
|
||||
echo >&2 "Enabled mpw_xml (libxml2)."
|
||||
cflags+=( -D"MPW_XML=1" -I"/usr/include/libxml2" -I"/usr/local/include/libxml2" ) ldflags+=( -l"xml2" )
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
### BUILD TARGETS
|
||||
for target in "${targets_all[@]}"; do
|
||||
if [[ ${targets:-$targets_default} == 'all' || " ${targets:-$targets_default} " = *" $target "* ]]; then
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
( "$target" "$@" )
|
||||
fi
|
||||
done
|
||||
|
||||
393
platform-independent/cli-c/cli/bcrypt.h
Normal file
393
platform-independent/cli-c/cli/bcrypt.h
Normal file
@@ -0,0 +1,393 @@
|
||||
/* $OpenBSD: bcrypt.c,v 1.57 2016/08/26 08:25:02 guenther Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Ted Unangst <tedu@openbsd.org>
|
||||
* Copyright (c) 1997 Niels Provos <provos@umich.edu>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
/* This password hashing algorithm was designed by David Mazieres
|
||||
* <dm@lcs.mit.edu> and works as follows:
|
||||
*
|
||||
* 1. state := InitState ()
|
||||
* 2. state := ExpandKey (state, salt, password)
|
||||
* 3. REPEAT rounds:
|
||||
* state := ExpandKey (state, 0, password)
|
||||
* state := ExpandKey (state, 0, salt)
|
||||
* 4. ctext := "OrpheanBeholderScryDoubt"
|
||||
* 5. REPEAT 64:
|
||||
* ctext := Encrypt_ECB (state, ctext);
|
||||
* 6. RETURN Concatenate (salt, ctext);
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "blf.h"
|
||||
#include "blowfish.h"
|
||||
|
||||
/* This implementation is adaptable to current computing power.
|
||||
* You can have up to 2^31 rounds which should be enough for some
|
||||
* time to come.
|
||||
*/
|
||||
|
||||
#define BCRYPT_VERSION '2'
|
||||
#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
|
||||
#define BCRYPT_WORDS 6 /* Ciphertext words */
|
||||
#define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */
|
||||
|
||||
#define BCRYPT_SALTSPACE (7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1)
|
||||
#define BCRYPT_HASHSPACE 61
|
||||
|
||||
static int encode_base64(char *, const uint8_t *, size_t);
|
||||
static int decode_base64(uint8_t *, size_t, const char *);
|
||||
|
||||
/*
|
||||
* Generates a salt for this version of crypt.
|
||||
*/
|
||||
static int
|
||||
bcrypt_initsalt(int log_rounds, uint8_t *salt, size_t saltbuflen) {
|
||||
|
||||
uint8_t csalt[BCRYPT_MAXSALT];
|
||||
|
||||
if (saltbuflen < BCRYPT_SALTSPACE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
arc4random_buf( csalt, sizeof( csalt ) );
|
||||
|
||||
if (log_rounds < 4)
|
||||
log_rounds = 4;
|
||||
else if (log_rounds > 31)
|
||||
log_rounds = 31;
|
||||
|
||||
snprintf( (char *)salt, saltbuflen, "$2b$%2.2u$", log_rounds );
|
||||
encode_base64( (char *)salt + 7, csalt, sizeof( csalt ) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the core bcrypt function
|
||||
*/
|
||||
static int
|
||||
bcrypt_hashpass(const char *key, const uint8_t *salt, char *encrypted,
|
||||
size_t encryptedlen) {
|
||||
|
||||
blf_ctx state;
|
||||
uint32_t rounds, i, k;
|
||||
uint16_t j;
|
||||
size_t key_len;
|
||||
uint8_t salt_len, logr, minor;
|
||||
uint8_t ciphertext[4 * BCRYPT_WORDS] = "OrpheanBeholderScryDoubt";
|
||||
uint8_t csalt[BCRYPT_MAXSALT];
|
||||
uint32_t cdata[BCRYPT_WORDS];
|
||||
|
||||
if (encryptedlen < BCRYPT_HASHSPACE)
|
||||
goto inval;
|
||||
|
||||
/* Check and discard "$" identifier */
|
||||
if (salt[0] != '$')
|
||||
goto inval;
|
||||
salt += 1;
|
||||
|
||||
if (salt[0] != BCRYPT_VERSION)
|
||||
goto inval;
|
||||
|
||||
/* Check for minor versions */
|
||||
switch ((minor = salt[1])) {
|
||||
case 'a':
|
||||
key_len = (uint8_t)(strlen( key ) + 1);
|
||||
break;
|
||||
case 'b':
|
||||
/* strlen() returns a size_t, but the function calls
|
||||
* below result in implicit casts to a narrower integer
|
||||
* type, so cap key_len at the actual maximum supported
|
||||
* length here to avoid integer wraparound */
|
||||
key_len = strlen( key );
|
||||
if (key_len > 72)
|
||||
key_len = 72;
|
||||
key_len++; /* include the NUL */
|
||||
break;
|
||||
default:
|
||||
goto inval;
|
||||
}
|
||||
if (salt[2] != '$')
|
||||
goto inval;
|
||||
/* Discard version + "$" identifier */
|
||||
salt += 3;
|
||||
|
||||
/* Check and parse num rounds */
|
||||
if (!isdigit( (unsigned char)salt[0] ) ||
|
||||
!isdigit( (unsigned char)salt[1] ) || salt[2] != '$')
|
||||
goto inval;
|
||||
logr = (uint8_t)((salt[1] - '0') + ((salt[0] - '0') * 10));
|
||||
if (logr < BCRYPT_MINLOGROUNDS || logr > 31)
|
||||
goto inval;
|
||||
/* Computer power doesn't increase linearly, 2^x should be fine */
|
||||
rounds = 1U << logr;
|
||||
|
||||
/* Discard num rounds + "$" identifier */
|
||||
salt += 3;
|
||||
|
||||
if (strlen( (char *)salt ) * 3 / 4 < BCRYPT_MAXSALT)
|
||||
goto inval;
|
||||
|
||||
/* We dont want the base64 salt but the raw data */
|
||||
if (decode_base64( csalt, BCRYPT_MAXSALT, (char *)salt ))
|
||||
goto inval;
|
||||
salt_len = BCRYPT_MAXSALT;
|
||||
|
||||
/* Setting up S-Boxes and Subkeys */
|
||||
Blowfish_initstate( &state );
|
||||
Blowfish_expandstate( &state, csalt, salt_len,
|
||||
(uint8_t *)key, (uint16_t)key_len );
|
||||
for (k = 0; k < rounds; k++) {
|
||||
Blowfish_expand0state( &state, (uint8_t *)key, (uint16_t)key_len );
|
||||
Blowfish_expand0state( &state, csalt, salt_len );
|
||||
}
|
||||
|
||||
/* This can be precomputed later */
|
||||
j = 0;
|
||||
for (i = 0; i < BCRYPT_WORDS; i++)
|
||||
cdata[i] = Blowfish_stream2word( ciphertext, 4 * BCRYPT_WORDS, &j );
|
||||
|
||||
/* Now do the encryption */
|
||||
for (k = 0; k < 64; k++)
|
||||
blf_enc( &state, cdata, BCRYPT_WORDS / 2 );
|
||||
|
||||
for (i = 0; i < BCRYPT_WORDS; i++) {
|
||||
ciphertext[4 * i + 3] = (uint8_t)(cdata[i] & 0xff);
|
||||
cdata[i] = cdata[i] >> 8;
|
||||
ciphertext[4 * i + 2] = (uint8_t)(cdata[i] & 0xff);
|
||||
cdata[i] = cdata[i] >> 8;
|
||||
ciphertext[4 * i + 1] = (uint8_t)(cdata[i] & 0xff);
|
||||
cdata[i] = cdata[i] >> 8;
|
||||
ciphertext[4 * i + 0] = (uint8_t)(cdata[i] & 0xff);
|
||||
}
|
||||
|
||||
snprintf( encrypted, 8, "$2%c$%2.2u$", minor, logr );
|
||||
encode_base64( encrypted + 7, csalt, BCRYPT_MAXSALT );
|
||||
encode_base64( encrypted + 7 + 22, ciphertext, 4 * BCRYPT_WORDS - 1 );
|
||||
bzero( &state, sizeof( state ) );
|
||||
bzero( ciphertext, sizeof( ciphertext ) );
|
||||
bzero( csalt, sizeof( csalt ) );
|
||||
bzero( cdata, sizeof( cdata ) );
|
||||
return 0;
|
||||
|
||||
inval:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* user friendly functions
|
||||
*/
|
||||
static int
|
||||
bcrypt_newhash(const char *pass, int log_rounds, char *hash, size_t hashlen) {
|
||||
|
||||
uint8_t salt[BCRYPT_SALTSPACE];
|
||||
|
||||
if (bcrypt_initsalt( log_rounds, salt, sizeof( salt ) ) != 0)
|
||||
return -1;
|
||||
|
||||
if (bcrypt_hashpass( pass, salt, hash, hashlen ) != 0)
|
||||
return -1;
|
||||
|
||||
bzero( salt, sizeof( salt ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __unused
|
||||
bcrypt_checkpass(const char *pass, const char *goodhash) {
|
||||
|
||||
char hash[BCRYPT_HASHSPACE];
|
||||
|
||||
if (bcrypt_hashpass( pass, (const uint8_t *)goodhash, hash, sizeof( hash ) ) != 0)
|
||||
return -1;
|
||||
if (strlen( hash ) != strlen( goodhash ) ||
|
||||
timingsafe_bcmp( hash, goodhash, strlen( goodhash ) ) != 0) {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero( hash, sizeof( hash ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Measure this system's performance by measuring the time for 8 rounds.
|
||||
* We are aiming for something that takes around 0.1s, but not too much over.
|
||||
*/
|
||||
static int __unused
|
||||
_bcrypt_autorounds(void) {
|
||||
|
||||
struct timespec before, after;
|
||||
int r = 8;
|
||||
char buf[_PASSWORD_LEN];
|
||||
time_t duration;
|
||||
|
||||
clock_gettime( CLOCK_THREAD_CPUTIME_ID, &before );
|
||||
bcrypt_newhash( "testpassword", r, buf, sizeof( buf ) );
|
||||
clock_gettime( CLOCK_THREAD_CPUTIME_ID, &after );
|
||||
|
||||
duration = after.tv_sec - before.tv_sec;
|
||||
duration *= 1000000;
|
||||
duration += (after.tv_nsec - before.tv_nsec) / 1000;
|
||||
|
||||
/* too quick? slow it down. */
|
||||
while (r < 16 && duration <= 60000) {
|
||||
r += 1;
|
||||
duration *= 2;
|
||||
}
|
||||
/* too slow? speed it up. */
|
||||
while (r > 6 && duration > 120000) {
|
||||
r -= 1;
|
||||
duration /= 2;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* internal utilities
|
||||
*/
|
||||
static const uint8_t Base64Code[] =
|
||||
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
static const uint8_t index_64[128] = {
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
|
||||
56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
|
||||
255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
|
||||
255, 255, 255, 255, 255, 255, 28, 29, 30,
|
||||
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||
51, 52, 53, 255, 255, 255, 255, 255
|
||||
};
|
||||
#define CHAR64(c) ( (c) > 127 ? (uint8_t)255 : index_64[(c)])
|
||||
|
||||
/*
|
||||
* read buflen (after decoding) bytes of data from b64data
|
||||
*/
|
||||
static int
|
||||
decode_base64(uint8_t *buffer, size_t len, const char *b64data) {
|
||||
|
||||
uint8_t *bp = buffer;
|
||||
const uint8_t *p = (uint8_t *)b64data;
|
||||
uint8_t c1, c2, c3, c4;
|
||||
|
||||
while (bp < buffer + len) {
|
||||
c1 = CHAR64( *p );
|
||||
/* Invalid data */
|
||||
if (c1 == 255)
|
||||
return -1;
|
||||
|
||||
c2 = CHAR64( *(p + 1) );
|
||||
if (c2 == 255)
|
||||
return -1;
|
||||
|
||||
*bp++ = (uint8_t)((c1 << 2) | ((c2 & 0x30) >> 4));
|
||||
if (bp >= buffer + len)
|
||||
break;
|
||||
|
||||
c3 = CHAR64( *(p + 2) );
|
||||
if (c3 == 255)
|
||||
return -1;
|
||||
|
||||
*bp++ = (uint8_t)(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));
|
||||
if (bp >= buffer + len)
|
||||
break;
|
||||
|
||||
c4 = CHAR64( *(p + 3) );
|
||||
if (c4 == 255)
|
||||
return -1;
|
||||
*bp++ = (uint8_t)(((c3 & 0x03) << 6) | c4);
|
||||
|
||||
p += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn len bytes of data into base64 encoded data.
|
||||
* This works without = padding.
|
||||
*/
|
||||
static int
|
||||
encode_base64(char *b64buffer, const uint8_t *data, size_t len) {
|
||||
|
||||
uint8_t *bp = (uint8_t *)b64buffer;
|
||||
const uint8_t *p = data;
|
||||
uint8_t c1, c2;
|
||||
|
||||
while (p < data + len) {
|
||||
c1 = *p++;
|
||||
*bp++ = Base64Code[(c1 >> 2)];
|
||||
c1 = (uint8_t)((c1 & 0x03) << 4);
|
||||
if (p >= data + len) {
|
||||
*bp++ = Base64Code[c1];
|
||||
break;
|
||||
}
|
||||
c2 = *p++;
|
||||
c1 |= (c2 >> 4) & 0x0f;
|
||||
*bp++ = Base64Code[c1];
|
||||
c1 = (uint8_t)((c2 & 0x0f) << 2);
|
||||
if (p >= data + len) {
|
||||
*bp++ = Base64Code[c1];
|
||||
break;
|
||||
}
|
||||
c2 = *p++;
|
||||
c1 |= (c2 >> 6) & 0x03;
|
||||
*bp++ = Base64Code[c1];
|
||||
*bp++ = Base64Code[c2 & 0x3f];
|
||||
}
|
||||
*bp = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* classic interface
|
||||
*/
|
||||
static uint8_t *
|
||||
bcrypt_gensalt(uint8_t log_rounds) {
|
||||
|
||||
static uint8_t gsalt[BCRYPT_SALTSPACE];
|
||||
|
||||
bcrypt_initsalt( log_rounds, gsalt, sizeof( gsalt ) );
|
||||
|
||||
return gsalt;
|
||||
}
|
||||
|
||||
static char *
|
||||
bcrypt(const char *pass, const uint8_t *salt) {
|
||||
|
||||
static char gencrypted[BCRYPT_HASHSPACE];
|
||||
|
||||
if (bcrypt_hashpass( pass, salt, gencrypted, sizeof( gencrypted ) ) != 0)
|
||||
return NULL;
|
||||
|
||||
return gencrypted;
|
||||
}
|
||||
81
platform-independent/cli-c/cli/blf.h
Normal file
81
platform-independent/cli-c/cli/blf.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
|
||||
/*
|
||||
* Blowfish - a fast block cipher designed by Bruce Schneier
|
||||
*
|
||||
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Niels Provos.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BLF_H_
|
||||
#define _BLF_H_
|
||||
|
||||
/* Schneier specifies a maximum key length of 56 bytes.
|
||||
* This ensures that every key bit affects every cipher
|
||||
* bit. However, the subkeys can hold up to 72 bytes.
|
||||
* Warning: For normal blowfish encryption only 56 bytes
|
||||
* of the key affect all cipherbits.
|
||||
*/
|
||||
|
||||
#define BLF_N 16 /* Number of Subkeys */
|
||||
#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
|
||||
#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */
|
||||
|
||||
/* Blowfish context */
|
||||
typedef struct BlowfishContext {
|
||||
u_int32_t S[4][256]; /* S-Boxes */
|
||||
u_int32_t P[BLF_N + 2]; /* Subkeys */
|
||||
} blf_ctx;
|
||||
|
||||
/* Raw access to customized Blowfish
|
||||
* blf_key is just:
|
||||
* Blowfish_initstate( state )
|
||||
* Blowfish_expand0state( state, key, keylen )
|
||||
*/
|
||||
|
||||
void Blowfish_encipher(blf_ctx *, u_int32_t *, u_int32_t *);
|
||||
void Blowfish_decipher(blf_ctx *, u_int32_t *, u_int32_t *);
|
||||
void Blowfish_initstate(blf_ctx *);
|
||||
void Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t);
|
||||
void Blowfish_expandstate(blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t);
|
||||
|
||||
/* Standard Blowfish */
|
||||
|
||||
void blf_key(blf_ctx *, const u_int8_t *, u_int16_t);
|
||||
void blf_enc(blf_ctx *, u_int32_t *, u_int16_t);
|
||||
void blf_dec(blf_ctx *, u_int32_t *, u_int16_t);
|
||||
|
||||
void blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t);
|
||||
void blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t);
|
||||
|
||||
void blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);
|
||||
void blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);
|
||||
|
||||
/* Converts u_int8_t to u_int32_t */
|
||||
u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t, u_int16_t *);
|
||||
|
||||
#endif
|
||||
640
platform-independent/cli-c/cli/blowfish.h
Normal file
640
platform-independent/cli-c/cli/blowfish.h
Normal file
@@ -0,0 +1,640 @@
|
||||
/* $OpenBSD: blowfish.c,v 1.19 2015/09/11 09:18:27 guenther Exp $ */
|
||||
/*
|
||||
* Blowfish block cipher for OpenBSD
|
||||
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Implementation advice by David Mazieres <dm@lcs.mit.edu>.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Niels Provos.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is derived from section 14.3 and the given source
|
||||
* in section V of Applied Cryptography, second edition.
|
||||
* Blowfish is an unpatented fast block cipher designed by
|
||||
* Bruce Schneier.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include <stdio.h> /* used for debugging */
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "blf.h"
|
||||
|
||||
#undef inline
|
||||
#ifdef __GNUC__
|
||||
#define inline __inline
|
||||
#else /* !__GNUC__ */
|
||||
#define inline
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
/* Function for Feistel Networks */
|
||||
|
||||
#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
|
||||
+ (s)[0x100 + (((x)>>16)&0xFF)]) \
|
||||
^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
|
||||
+ (s)[0x300 + ( (x) &0xFF)])
|
||||
|
||||
#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
|
||||
|
||||
void
|
||||
Blowfish_encipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr)
|
||||
{
|
||||
u_int32_t Xl;
|
||||
u_int32_t Xr;
|
||||
u_int32_t *s = c->S[0];
|
||||
u_int32_t *p = c->P;
|
||||
|
||||
Xl = *xl;
|
||||
Xr = *xr;
|
||||
|
||||
Xl ^= p[0];
|
||||
BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
|
||||
BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
|
||||
BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
|
||||
BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
|
||||
BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
|
||||
BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
|
||||
BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
|
||||
BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
|
||||
|
||||
*xl = Xr ^ p[17];
|
||||
*xr = Xl;
|
||||
}
|
||||
|
||||
void
|
||||
Blowfish_decipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr)
|
||||
{
|
||||
u_int32_t Xl;
|
||||
u_int32_t Xr;
|
||||
u_int32_t *s = c->S[0];
|
||||
u_int32_t *p = c->P;
|
||||
|
||||
Xl = *xl;
|
||||
Xr = *xr;
|
||||
|
||||
Xl ^= p[17];
|
||||
BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
|
||||
BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
|
||||
BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
|
||||
BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
|
||||
BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
|
||||
BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
|
||||
BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
|
||||
BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
|
||||
|
||||
*xl = Xr ^ p[0];
|
||||
*xr = Xl;
|
||||
}
|
||||
|
||||
void
|
||||
Blowfish_initstate(blf_ctx *c)
|
||||
{
|
||||
/* P-box and S-box tables initialized with digits of Pi */
|
||||
|
||||
static const blf_ctx initstate =
|
||||
{ {
|
||||
{
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
|
||||
{
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
|
||||
{
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
|
||||
{
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
|
||||
},
|
||||
{
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||
0x9216d5d9, 0x8979fb1b
|
||||
} };
|
||||
|
||||
*c = initstate;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes,
|
||||
u_int16_t *current)
|
||||
{
|
||||
u_int8_t i;
|
||||
u_int16_t j;
|
||||
u_int32_t temp;
|
||||
|
||||
temp = 0x00000000;
|
||||
j = *current;
|
||||
|
||||
for (i = 0; i < 4; i++, j++) {
|
||||
if (j >= databytes)
|
||||
j = 0;
|
||||
temp = (temp << 8) | data[j];
|
||||
}
|
||||
|
||||
*current = j;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes)
|
||||
{
|
||||
u_int16_t i;
|
||||
u_int16_t j;
|
||||
u_int16_t k;
|
||||
u_int32_t temp;
|
||||
u_int32_t datal;
|
||||
u_int32_t datar;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < BLF_N + 2; i++) {
|
||||
/* Extract 4 int8 to 1 int32 from keystream */
|
||||
temp = Blowfish_stream2word(key, keybytes, &j);
|
||||
c->P[i] = c->P[i] ^ temp;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
datal = 0x00000000;
|
||||
datar = 0x00000000;
|
||||
for (i = 0; i < BLF_N + 2; i += 2) {
|
||||
Blowfish_encipher(c, &datal, &datar);
|
||||
|
||||
c->P[i] = datal;
|
||||
c->P[i + 1] = datar;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (k = 0; k < 256; k += 2) {
|
||||
Blowfish_encipher(c, &datal, &datar);
|
||||
|
||||
c->S[i][k] = datal;
|
||||
c->S[i][k + 1] = datar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes,
|
||||
const u_int8_t *key, u_int16_t keybytes)
|
||||
{
|
||||
u_int16_t i;
|
||||
u_int16_t j;
|
||||
u_int16_t k;
|
||||
u_int32_t temp;
|
||||
u_int32_t datal;
|
||||
u_int32_t datar;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < BLF_N + 2; i++) {
|
||||
/* Extract 4 int8 to 1 int32 from keystream */
|
||||
temp = Blowfish_stream2word(key, keybytes, &j);
|
||||
c->P[i] = c->P[i] ^ temp;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
datal = 0x00000000;
|
||||
datar = 0x00000000;
|
||||
for (i = 0; i < BLF_N + 2; i += 2) {
|
||||
datal ^= Blowfish_stream2word(data, databytes, &j);
|
||||
datar ^= Blowfish_stream2word(data, databytes, &j);
|
||||
Blowfish_encipher(c, &datal, &datar);
|
||||
|
||||
c->P[i] = datal;
|
||||
c->P[i + 1] = datar;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (k = 0; k < 256; k += 2) {
|
||||
datal ^= Blowfish_stream2word(data, databytes, &j);
|
||||
datar ^= Blowfish_stream2word(data, databytes, &j);
|
||||
Blowfish_encipher(c, &datal, &datar);
|
||||
|
||||
c->S[i][k] = datal;
|
||||
c->S[i][k + 1] = datar;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
__unused blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len)
|
||||
{
|
||||
/* Initialize S-boxes and subkeys with Pi */
|
||||
Blowfish_initstate(c);
|
||||
|
||||
/* Transform S-boxes and subkeys with key */
|
||||
Blowfish_expand0state(c, k, len);
|
||||
}
|
||||
|
||||
void
|
||||
blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
|
||||
{
|
||||
u_int32_t *d;
|
||||
u_int16_t i;
|
||||
|
||||
d = data;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
Blowfish_encipher(c, d, d + 1);
|
||||
d += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__unused blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
|
||||
{
|
||||
u_int32_t *d;
|
||||
u_int16_t i;
|
||||
|
||||
d = data;
|
||||
for (i = 0; i < blocks; i++) {
|
||||
Blowfish_decipher(c, d, d + 1);
|
||||
d += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__unused blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
|
||||
{
|
||||
u_int32_t l, r;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < len; i += 8) {
|
||||
l = (u_int32_t)data[0] << 24 | (u_int32_t)data[1] << 16 | (u_int32_t)data[2] << 8 | (u_int32_t)data[3];
|
||||
r = (u_int32_t)data[4] << 24 | (u_int32_t)data[5] << 16 | (u_int32_t)data[6] << 8 | (u_int32_t)data[7];
|
||||
Blowfish_encipher(c, &l, &r);
|
||||
data[0] = (u_int8_t)(l >> 24 & 0xff);
|
||||
data[1] = (u_int8_t)(l >> 16 & 0xff);
|
||||
data[2] = (u_int8_t)(l >> 8 & 0xff);
|
||||
data[3] = (u_int8_t)(l & 0xff);
|
||||
data[4] = (u_int8_t)(r >> 24 & 0xff);
|
||||
data[5] = (u_int8_t)(r >> 16 & 0xff);
|
||||
data[6] = (u_int8_t)(r >> 8 & 0xff);
|
||||
data[7] = (u_int8_t)(r & 0xff);
|
||||
data += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__unused blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
|
||||
{
|
||||
u_int32_t l, r;
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < len; i += 8) {
|
||||
l = (u_int32_t)data[0] << 24 | (u_int32_t)data[1] << 16 | (u_int32_t)data[2] << 8 | (u_int32_t)data[3];
|
||||
r = (u_int32_t)data[4] << 24 | (u_int32_t)data[5] << 16 | (u_int32_t)data[6] << 8 | (u_int32_t)data[7];
|
||||
Blowfish_decipher(c, &l, &r);
|
||||
data[0] = (u_int8_t)(l >> 24 & 0xff);
|
||||
data[1] = (u_int8_t)(l >> 16 & 0xff);
|
||||
data[2] = (u_int8_t)(l >> 8 & 0xff);
|
||||
data[3] = (u_int8_t)(l & 0xff);
|
||||
data[4] = (u_int8_t)(r >> 24 & 0xff);
|
||||
data[5] = (u_int8_t)(r >> 16 & 0xff);
|
||||
data[6] = (u_int8_t)(r >> 8 & 0xff);
|
||||
data[7] = (u_int8_t)(r & 0xff);
|
||||
data += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__unused blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len)
|
||||
{
|
||||
u_int32_t l, r;
|
||||
u_int32_t i, j;
|
||||
|
||||
for (i = 0; i < len; i += 8) {
|
||||
for (j = 0; j < 8; j++)
|
||||
data[j] ^= iv[j];
|
||||
l = (u_int32_t)data[0] << 24 | (u_int32_t)data[1] << 16 | (u_int32_t)data[2] << 8 | (u_int32_t)data[3];
|
||||
r = (u_int32_t)data[4] << 24 | (u_int32_t)data[5] << 16 | (u_int32_t)data[6] << 8 | (u_int32_t)data[7];
|
||||
Blowfish_encipher(c, &l, &r);
|
||||
data[0] = (u_int8_t)(l >> 24 & 0xff);
|
||||
data[1] = (u_int8_t)(l >> 16 & 0xff);
|
||||
data[2] = (u_int8_t)(l >> 8 & 0xff);
|
||||
data[3] = (u_int8_t)(l & 0xff);
|
||||
data[4] = (u_int8_t)(r >> 24 & 0xff);
|
||||
data[5] = (u_int8_t)(r >> 16 & 0xff);
|
||||
data[6] = (u_int8_t)(r >> 8 & 0xff);
|
||||
data[7] = (u_int8_t)(r & 0xff);
|
||||
iv = data;
|
||||
data += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__unused blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len)
|
||||
{
|
||||
u_int32_t l, r;
|
||||
u_int8_t *iv;
|
||||
u_int32_t i, j;
|
||||
|
||||
iv = data + len - 16;
|
||||
data = data + len - 8;
|
||||
for (i = len - 8; i >= 8; i -= 8) {
|
||||
l = (u_int32_t)data[0] << 24 | (u_int32_t)data[1] << 16 | (u_int32_t)data[2] << 8 | (u_int32_t)data[3];
|
||||
r = (u_int32_t)data[4] << 24 | (u_int32_t)data[5] << 16 | (u_int32_t)data[6] << 8 | (u_int32_t)data[7];
|
||||
Blowfish_decipher(c, &l, &r);
|
||||
data[0] = (u_int8_t)(l >> 24 & 0xff);
|
||||
data[1] = (u_int8_t)(l >> 16 & 0xff);
|
||||
data[2] = (u_int8_t)(l >> 8 & 0xff);
|
||||
data[3] = (u_int8_t)(l & 0xff);
|
||||
data[4] = (u_int8_t)(r >> 24 & 0xff);
|
||||
data[5] = (u_int8_t)(r >> 16 & 0xff);
|
||||
data[6] = (u_int8_t)(r >> 8 & 0xff);
|
||||
data[7] = (u_int8_t)(r & 0xff);
|
||||
for (j = 0; j < 8; j++)
|
||||
data[j] ^= iv[j];
|
||||
iv -= 8;
|
||||
data -= 8;
|
||||
}
|
||||
l = (u_int32_t)data[0] << 24 | (u_int32_t)data[1] << 16 | (u_int32_t)data[2] << 8 | (u_int32_t)data[3];
|
||||
r = (u_int32_t)data[4] << 24 | (u_int32_t)data[5] << 16 | (u_int32_t)data[6] << 8 | (u_int32_t)data[7];
|
||||
Blowfish_decipher(c, &l, &r);
|
||||
data[0] = (u_int8_t)(l >> 24 & 0xff);
|
||||
data[1] = (u_int8_t)(l >> 16 & 0xff);
|
||||
data[2] = (u_int8_t)(l >> 8 & 0xff);
|
||||
data[3] = (u_int8_t)(l & 0xff);
|
||||
data[4] = (u_int8_t)(r >> 24 & 0xff);
|
||||
data[5] = (u_int8_t)(r >> 16 & 0xff);
|
||||
data[6] = (u_int8_t)(r >> 8 & 0xff);
|
||||
data[7] = (u_int8_t)(r & 0xff);
|
||||
for (j = 0; j < 8; j++)
|
||||
data[j] ^= iva[j];
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <bcrypt/ow-crypt.h>
|
||||
#include "bcrypt.h"
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
@@ -39,7 +39,7 @@ static const double mpw_showSpeed(struct timeval startTime, const unsigned int i
|
||||
const double speed = iterations / elapsed;
|
||||
|
||||
fprintf( stderr, " done. " );
|
||||
fprintf( stdout, "%d %s iterations in %llds %lldµs -> %.2f/s\n", iterations, operation, (long long)dsec, (long long)dusec, speed );
|
||||
fprintf( stdout, "%d %s iterations in %lus %uµs -> %.2f/s\n", iterations, operation, dsec, dusec, speed );
|
||||
|
||||
return speed;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ int main(int argc, char *const argv[]) {
|
||||
// Start HMAC-SHA-256
|
||||
// Similar to phase-two of mpw
|
||||
uint8_t *sitePasswordInfo = malloc( 128 );
|
||||
iterations = 3000000;
|
||||
iterations = 4200000; /* tuned to ~10s on dev machine */
|
||||
masterKey = mpw_masterKey( fullName, masterPassword, MPAlgorithmVersionCurrent );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %s\n", strerror( errno ) );
|
||||
@@ -79,20 +79,20 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
// Start BCrypt
|
||||
// Similar to phase-one of mpw
|
||||
int bcrypt_cost = 9;
|
||||
iterations = 1000;
|
||||
uint8_t bcrypt_rounds = 9;
|
||||
iterations = 170; /* tuned to ~10s on dev machine */
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 1; i <= iterations; ++i) {
|
||||
crypt( masterPassword, crypt_gensalt( "$2b$", bcrypt_cost, fullName, strlen( fullName ) ) );
|
||||
bcrypt( masterPassword, bcrypt_gensalt( bcrypt_rounds ) );
|
||||
|
||||
if (modff( 100.f * i / iterations, &percent ) == 0)
|
||||
fprintf( stderr, "\rbcrypt (cost %d): iteration %d / %d (%.0f%%)..", bcrypt_cost, i, iterations, percent );
|
||||
fprintf( stderr, "\rbcrypt (rounds 10^%d): iteration %d / %d (%.0f%%)..", bcrypt_rounds, i, iterations, percent );
|
||||
}
|
||||
const double bcrypt9Speed = mpw_showSpeed( startTime, iterations, "bcrypt9" );
|
||||
const double bcrypt9Speed = mpw_showSpeed( startTime, iterations, "bcrypt" );
|
||||
|
||||
// Start SCrypt
|
||||
// Phase one of mpw
|
||||
iterations = 50;
|
||||
iterations = 50; /* tuned to ~10s on dev machine */
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 1; i <= iterations; ++i) {
|
||||
free( (void *)mpw_masterKey( fullName, masterPassword, MPAlgorithmVersionCurrent ) );
|
||||
@@ -104,7 +104,7 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
// Start MPW
|
||||
// Both phases of mpw
|
||||
iterations = 50;
|
||||
iterations = 50; /* tuned to ~10s on dev machine */
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 1; i <= iterations; ++i) {
|
||||
masterKey = mpw_masterKey( fullName, masterPassword, MPAlgorithmVersionCurrent );
|
||||
@@ -124,9 +124,9 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
// Summarize.
|
||||
fprintf( stdout, "\n== SUMMARY ==\nOn this machine,\n" );
|
||||
fprintf( stdout, " - mpw is %f times slower than hmac-sha-256 (reference: 320000 on an MBP Late 2013).\n", hmacSha256Speed / mpwSpeed );
|
||||
fprintf( stdout, " - mpw is %f times slower than bcrypt (cost 9) (reference: 22 on an MBP Late 2013).\n", bcrypt9Speed / mpwSpeed );
|
||||
fprintf( stdout, " - scrypt is %f times slower than bcrypt (cost 9) (reference: 22 on an MBP Late 2013).\n", bcrypt9Speed / scryptSpeed );
|
||||
fprintf( stdout, " - mpw is %f times slower than hmac-sha-256.\n", hmacSha256Speed / mpwSpeed );
|
||||
fprintf( stdout, " - mpw is %f times slower than bcrypt (rounds 10^%d).\n", bcrypt9Speed / mpwSpeed, bcrypt_rounds );
|
||||
fprintf( stdout, " - scrypt is %f times slower than bcrypt (rounds 10^%d).\n", bcrypt9Speed / scryptSpeed, bcrypt_rounds );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
244
platform-independent/cli-c/cli/mpw-cli-util.c
Normal file
244
platform-independent/cli-c/cli/mpw-cli-util.c
Normal file
@@ -0,0 +1,244 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
#include "mpw-cli-util.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
/** Read the value of an environment variable.
|
||||
* @return A newly allocated string or NULL if the variable doesn't exist. */
|
||||
const char *mpw_getenv(const char *variableName) {
|
||||
|
||||
char *envBuf = getenv( variableName );
|
||||
return envBuf? strdup( envBuf ): NULL;
|
||||
}
|
||||
|
||||
/** Use the askpass program to prompt the user.
|
||||
* @return A newly allocated string or NULL if askpass is not supported or an error occurred. */
|
||||
char *mpw_askpass(const char *prompt) {
|
||||
|
||||
const char *askpass = mpw_getenv( MP_ENV_askpass );
|
||||
if (!askpass)
|
||||
return NULL;
|
||||
|
||||
int pipes[2];
|
||||
if (pipe( pipes ) == ERR) {
|
||||
wrn( "Couldn't pipe: %s\n", strerror( errno ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == ERR) {
|
||||
wrn( "Couldn't fork for askpass:\n %s: %s\n", askpass, strerror( errno ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!pid) {
|
||||
// askpass fork
|
||||
close( pipes[0] );
|
||||
if (dup2( pipes[1], STDOUT_FILENO ) == ERR)
|
||||
ftl( "Couldn't connect pipe to process: %s\n", strerror( errno ) );
|
||||
|
||||
else if (execlp( askpass, askpass, prompt, NULL ) == ERR)
|
||||
ftl( "Couldn't execute askpass:\n %s: %s\n", askpass, strerror( errno ) );
|
||||
|
||||
exit( EX_SOFTWARE );
|
||||
}
|
||||
|
||||
close( pipes[1] );
|
||||
char *answer = mpw_read_fd( pipes[0] );
|
||||
close( pipes[0] );
|
||||
int status;
|
||||
if (waitpid( pid, &status, 0 ) == ERR) {
|
||||
wrn( "Couldn't wait for askpass: %s\n", strerror( errno ) );
|
||||
mpw_free_string( &answer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (WIFEXITED( status ) && WEXITSTATUS( status ) == EXIT_SUCCESS && answer && strlen( answer )) {
|
||||
// Remove trailing newline.
|
||||
if (answer[strlen( answer ) - 1] == '\n')
|
||||
answer[strlen( answer ) - 1] = '\0';
|
||||
return answer;
|
||||
}
|
||||
|
||||
mpw_free_string( &answer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Ask the user a question.
|
||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||
const char *mpw_getline(const char *prompt) {
|
||||
|
||||
// Get answer from askpass.
|
||||
char *answer = mpw_askpass( prompt );
|
||||
if (answer)
|
||||
return answer;
|
||||
|
||||
// Get password from terminal.
|
||||
fprintf( stderr, "%s ", prompt );
|
||||
|
||||
size_t bufSize = 0;
|
||||
ssize_t lineSize = getline( &answer, &bufSize, stdin );
|
||||
if (lineSize <= 1) {
|
||||
mpw_free_string( &answer );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Remove trailing newline.
|
||||
answer[lineSize - 1] = '\0';
|
||||
return answer;
|
||||
}
|
||||
|
||||
/** Ask the user for a password.
|
||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||
const char *mpw_getpass(const char *prompt) {
|
||||
|
||||
// Get password from askpass.
|
||||
const char *password = mpw_askpass( prompt );
|
||||
if (password)
|
||||
return password;
|
||||
|
||||
// Get password from terminal.
|
||||
char *answer = getpass( prompt );
|
||||
if (!answer)
|
||||
return NULL;
|
||||
|
||||
password = strdup( answer );
|
||||
bzero( answer, strlen( answer ) );
|
||||
return password;
|
||||
}
|
||||
|
||||
/** Get the absolute path to the mpw configuration file with the given prefix name and file extension.
|
||||
* Resolves the file <prefix.extension> as located in the <.mpw.d> directory inside the user's home directory
|
||||
* or current directory if it couldn't be resolved.
|
||||
* @return A newly allocated string. */
|
||||
const char *mpw_path(const char *prefix, const char *extension) {
|
||||
|
||||
// Resolve user's home directory.
|
||||
char *homeDir = NULL;
|
||||
if (!homeDir)
|
||||
if ((homeDir = getenv( "HOME" )))
|
||||
homeDir = strdup( homeDir );
|
||||
if (!homeDir)
|
||||
if ((homeDir = getenv( "USERPROFILE" )))
|
||||
homeDir = strdup( homeDir );
|
||||
if (!homeDir) {
|
||||
const char *homeDrive = getenv( "HOMEDRIVE" ), *homePath = getenv( "HOMEPATH" );
|
||||
if (homeDrive && homePath)
|
||||
homeDir = strdup( mpw_str( "%s%s", homeDrive, homePath ) );
|
||||
}
|
||||
if (!homeDir) {
|
||||
struct passwd *passwd = getpwuid( getuid() );
|
||||
if (passwd)
|
||||
homeDir = strdup( passwd->pw_dir );
|
||||
}
|
||||
if (!homeDir)
|
||||
homeDir = getcwd( NULL, 0 );
|
||||
|
||||
// Compose filename.
|
||||
char *path = strdup( mpw_str( "%s.%s", prefix, extension ) );
|
||||
|
||||
// This is a filename, remove all potential directory separators.
|
||||
for (char *slash; (slash = strstr( path, "/" )); *slash = '_');
|
||||
|
||||
// Compose pathname.
|
||||
if (homeDir) {
|
||||
const char *homePath = mpw_str( "%s/.mpw.d/%s", homeDir, path );
|
||||
free( homeDir );
|
||||
free( path );
|
||||
|
||||
if (homePath)
|
||||
path = strdup( homePath );
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/** mkdir all the directories up to the directory of the given file path.
|
||||
* @return true if the file's path exists. */
|
||||
bool mpw_mkdirs(const char *filePath) {
|
||||
|
||||
if (!filePath)
|
||||
return false;
|
||||
|
||||
// The path to mkdir is the filePath without the last path component.
|
||||
char *pathEnd = strrchr( filePath, '/' );
|
||||
char *path = pathEnd? strndup( filePath, (size_t)(pathEnd - filePath) ): NULL;
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
// Save the cwd and for absolute paths, start at the root.
|
||||
char *cwd = getcwd( NULL, 0 );
|
||||
if (*filePath == '/')
|
||||
chdir( "/" );
|
||||
|
||||
// Walk the path.
|
||||
bool success = true;
|
||||
for (char *dirName = strtok( path, "/" ); success && dirName; dirName = strtok( NULL, "/" )) {
|
||||
if (!strlen( dirName ))
|
||||
continue;
|
||||
|
||||
success &= (mkdir( dirName, 0700 ) != ERR || errno == EEXIST) && chdir( dirName ) != ERR;
|
||||
}
|
||||
free( path );
|
||||
|
||||
if (chdir( cwd ) == ERR)
|
||||
wrn( "Could not restore cwd:\n %s: %s\n", cwd, strerror( errno ) );
|
||||
free( cwd );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/** Read until EOF from the given file descriptor.
|
||||
* @return A newly allocated string or NULL if the read buffer couldn't be allocated or an error occurred. */
|
||||
char *mpw_read_fd(int fd) {
|
||||
|
||||
char *buf = NULL;
|
||||
size_t blockSize = 4096, bufSize = 0, bufOffset = 0;
|
||||
ssize_t readSize = 0;
|
||||
while ((mpw_realloc( &buf, &bufSize, blockSize )) &&
|
||||
((readSize = read( fd, buf + bufOffset, blockSize )) > 0));
|
||||
if (readSize == ERR)
|
||||
mpw_free( &buf, bufSize );
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** Read the file contents of a given file.
|
||||
* @return A newly allocated string or NULL if the read buffer couldn't be allocated. */
|
||||
char *mpw_read_file(FILE *file) {
|
||||
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
char *buf = NULL;
|
||||
size_t blockSize = 4096, bufSize = 0, bufOffset = 0, readSize = 0;
|
||||
while ((mpw_realloc( &buf, &bufSize, blockSize )) &&
|
||||
(bufOffset += (readSize = fread( buf + bufOffset, 1, blockSize, file ))) &&
|
||||
(readSize == blockSize));
|
||||
|
||||
return buf;
|
||||
}
|
||||
64
platform-independent/cli-c/cli/mpw-cli-util.h
Normal file
64
platform-independent/cli-c/cli/mpw-cli-util.h
Normal file
@@ -0,0 +1,64 @@
|
||||
//==============================================================================
|
||||
// This file is part of Master Password.
|
||||
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||
//
|
||||
// Master Password is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Master Password is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You can find a copy of the GNU General Public License in the
|
||||
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||
//==============================================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef MP_VERSION
|
||||
#define MP_VERSION ?
|
||||
#endif
|
||||
|
||||
#define MP_ENV_fullName "MPW_FULLNAME"
|
||||
#define MP_ENV_algorithm "MPW_ALGORITHM"
|
||||
#define MP_ENV_format "MPW_FORMAT"
|
||||
#define MP_ENV_askpass "MPW_ASKPASS"
|
||||
|
||||
/** Read the value of an environment variable.
|
||||
* @return A newly allocated string or NULL if the variable doesn't exist. */
|
||||
const char *mpw_getenv(const char *variableName);
|
||||
|
||||
/** Use the askpass program to prompt the user.
|
||||
* @return A newly allocated string or NULL if askpass is not supported or an error occurred. */
|
||||
char *mpw_askpass(const char *prompt);
|
||||
|
||||
/** Ask the user a question.
|
||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||
const char *mpw_getline(const char *prompt);
|
||||
|
||||
/** Ask the user for a password.
|
||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||
const char *mpw_getpass(const char *prompt);
|
||||
|
||||
/** Get the absolute path to the mpw configuration file with the given prefix name and file extension.
|
||||
* Resolves the file <prefix.extension> as located in the <.mpw.d> directory inside the user's home directory
|
||||
* or current directory if it couldn't be resolved.
|
||||
* @return A newly allocated string. */
|
||||
const char *mpw_path(const char *prefix, const char *extension);
|
||||
|
||||
/** mkdir all the directories up to the directory of the given file path.
|
||||
* @return true if the file's path exists. */
|
||||
bool mpw_mkdirs(const char *filePath);
|
||||
|
||||
/** Read until EOF from the given file descriptor.
|
||||
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
||||
char *mpw_read_fd(int fd);
|
||||
|
||||
/** Read the file contents of a given file.
|
||||
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
||||
char *mpw_read_file(FILE *file);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@ int main(int argc, char *const argv[]) {
|
||||
// 2. calculate the site password.
|
||||
const char *sitePassword = mpw_siteResult(
|
||||
masterKey, (char *)siteName, siteCounter, keyPurpose, (char *)keyContext, resultType, NULL, algorithm );
|
||||
mpw_free( masterKey, MPMasterKeySize );
|
||||
mpw_free( &masterKey, MPMasterKeySize );
|
||||
if (!sitePassword) {
|
||||
ftl( "Couldn't derive site password.\n" );
|
||||
continue;
|
||||
@@ -72,7 +72,7 @@ int main(int argc, char *const argv[]) {
|
||||
}
|
||||
|
||||
// Free test case.
|
||||
mpw_free_string( sitePassword );
|
||||
mpw_free_string( &sitePassword );
|
||||
xmlFree( id );
|
||||
xmlFree( fullName );
|
||||
xmlFree( masterPassword );
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
tag=$(git describe --match '*-cli*')
|
||||
commit=$(git describe --long --dirty --match '*-cli*')
|
||||
[[ $commit != *-dirty ]] || { echo >&2 "Tree is dirty, first commit any changes."; exit 1; }
|
||||
tag=$(git describe --exact-match --match '*-cli*') || { echo >&2 "Tree is not at a release tag."; exit 1; }
|
||||
version=$(git describe --match '*-cli*' --long --dirty --broken)
|
||||
[[ $version != *-dirty ]] || { echo >&2 "Tree is dirty, first commit any changes."; exit 1; }
|
||||
|
||||
mpwArchive=mpw-$commit.tar.gz
|
||||
mpwArchive=mpw-$version.tar.gz
|
||||
[[ -e $mpwArchive ]] && echo >&2 "WARNING: $mpwArchive already exists. Will overwrite."
|
||||
read -n1 -p "Will prepare and release $mpwArchive. Press a key to continue or ^C to abort."
|
||||
|
||||
@@ -14,8 +14,9 @@ echo "Cleaning .."
|
||||
( git clean -ffdx . && cd core && git clean -ffdx . )
|
||||
|
||||
echo "Creating archive $mpwArchive .."
|
||||
git show --show-signature --pretty=format:%H --quiet "$tag" > VERSION
|
||||
git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive"
|
||||
echo "$version" > VERSION
|
||||
git show --show-signature --pretty=format:%H --quiet "$tag" > TAG
|
||||
{ git ls-files -z .; printf '%s\0' VERSION TAG; } | xargs -0 tar -Lcvzf "$mpwArchive"
|
||||
|
||||
echo "Creating archive signature $mpwArchive.sig .."
|
||||
gpg --detach-sign "$mpwArchive"
|
||||
|
||||
@@ -45,9 +45,20 @@ fi
|
||||
echo
|
||||
|
||||
inf "You can also save your user name in ~/.bashrc. Leave blank to skip this step."
|
||||
if MP_FULLNAME=$(ask "Your full name:") && [[ $MP_FULLNAME ]] ; then
|
||||
printf 'export MP_FULLNAME=%q\n' "$MP_FULLNAME" >> ~/.bashrc
|
||||
if MPW_FULLNAME=$(ask "Your full name:") && [[ $MPW_FULLNAME ]] ; then
|
||||
printf 'export MPW_FULLNAME=%q\n' "$MPW_FULLNAME" >> ~/.bashrc
|
||||
fi
|
||||
inf "If you have an askpass program you'd like to use, you can specify it here."
|
||||
inf "An askpass program provides a graphical interface for entering things like your master password."
|
||||
inf "Leave blank to skip this step and enter passwords using the terminal."
|
||||
if [[ ! $MPW_ASKPASS ]] && hash ssh-askpass 2>/dev/null; then
|
||||
MPW_ASKPASS=ssh-askpass
|
||||
fi
|
||||
if MPW_ASKPASS=$(ask +"$MPW_ASKPASS" "askpass program:") && [[ $MPW_ASKPASS ]] ; then
|
||||
printf 'export MPW_ASKPASS=%q\n' "$MPW_ASKPASS" >> ~/.bashrc
|
||||
fi
|
||||
echo
|
||||
|
||||
inf "To begin using Master Password, type: mpw [site name]"
|
||||
inf "Shell features installed."
|
||||
inf "To load these convenience features into your already running shell, type: source ~/.bashrc"
|
||||
inf "To begin using Master Password, type: mpw -h or mpw my-site-name"
|
||||
|
||||
103
platform-independent/cli-c/mpw-cli-tests
Executable file
103
platform-independent/cli-c/mpw-cli-tests
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env bash
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
|
||||
|
||||
# Tooling
|
||||
errors=0
|
||||
mpw_expect() {
|
||||
local expect=$1; shift
|
||||
|
||||
printf '.'
|
||||
result=$(./mpw -q "$@") err=$?
|
||||
|
||||
if (( err )); then
|
||||
printf >&2 "Error (exit %d) mpw%s\n" "$err" "$(printf ' %q' "$@")"
|
||||
return $(( ++errors ))
|
||||
fi
|
||||
if [[ $result != $expect ]]; then
|
||||
printf >&2 "Error (got: %s != expected: %s) mpw%s\n" "$result" "$expect" "$(printf ' %q' "$@")"
|
||||
return $(( ++errors ))
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# mpw_tests.xml
|
||||
## V3
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'NopaDajh8=Fene' -Fnone -u '⛄' -M 'banana colored duckling' -tlong -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'QesuHirv5-Xepl' -Fnone -u 'Robert Lee Mitchell' -M '⛄' -tlong -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'LiheCuwhSerz6)' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a3 -p 'authentication' -C '' '⛄'
|
||||
mpw_expect 'wohzaqage' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -p 'identification' 'masterpasswordapp.com'
|
||||
mpw_expect 'wohzaqage' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a3 -p 'identification' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'xin diyjiqoja hubu' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -p 'recovery' 'masterpasswordapp.com'
|
||||
mpw_expect 'xin diyjiqoja hubu' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a3 -p 'recovery' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'xogx tem cegyiva jab' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a3 -p 'recovery' -C 'question' 'masterpasswordapp.com'
|
||||
mpw_expect 'W6@692^B1#&@gVdSdLZ@' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmax -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jej2$Quv' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmed -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'WAo2xIg6' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tbasic -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jej2' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tshort -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect '7662' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tpin -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'jejraquvo' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'jejr quv cabsibu tam' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a3 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'XambHoqo6[Peni' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c4294967295 -a3 -p 'authentication' 'masterpasswordapp.com'
|
||||
|
||||
## V2
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'WaqoGuho2[Xaxw' -Fnone -u '⛄' -M 'banana colored duckling' -tlong -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'QesuHirv5-Xepl' -Fnone -u 'Robert Lee Mitchell' -M '⛄' -tlong -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'LiheCuwhSerz6)' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a2 -p 'authentication' -C '' '⛄'
|
||||
mpw_expect 'wohzaqage' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a2 -p 'identification' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'xin diyjiqoja hubu' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a2 -p 'recovery' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'xogx tem cegyiva jab' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a2 -p 'recovery' -C 'question' 'masterpasswordapp.com'
|
||||
mpw_expect 'W6@692^B1#&@gVdSdLZ@' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmax -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jej2$Quv' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmed -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'WAo2xIg6' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tbasic -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jej2' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tshort -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect '7662' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tpin -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'jejraquvo' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'jejr quv cabsibu tam' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a2 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'XambHoqo6[Peni' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c4294967295 -a2 -p 'authentication' 'masterpasswordapp.com'
|
||||
|
||||
## V1
|
||||
mpw_expect 'Jejr5[RepuSosp' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'WaqoGuho2[Xaxw' -Fnone -u '⛄' -M 'banana colored duckling' -tlong -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'QesuHirv5-Xepl' -Fnone -u 'Robert Lee Mitchell' -M '⛄' -tlong -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'WawiYarp2@Kodh' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a1 -p 'authentication' -C '' '⛄'
|
||||
mpw_expect 'wohzaqage' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a1 -p 'identification' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'xin diyjiqoja hubu' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a1 -p 'recovery' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'xogx tem cegyiva jab' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a1 -p 'recovery' -C 'question' 'masterpasswordapp.com'
|
||||
mpw_expect 'W6@692^B1#&@gVdSdLZ@' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmax -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jej2$Quv' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmed -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'WAo2xIg6' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tbasic -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Jej2' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tshort -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect '7662' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tpin -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'jejraquvo' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'jejr quv cabsibu tam' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a1 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'XambHoqo6[Peni' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c4294967295 -a1 -p 'authentication' 'masterpasswordapp.com'
|
||||
|
||||
## V0
|
||||
mpw_expect 'Feji5@ReduWosh' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'HajrYudo7@Mamh' -Fnone -u '⛄' -M 'banana colored duckling' -tlong -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'MewmDini0]Meho' -Fnone -u 'Robert Lee Mitchell' -M '⛄' -tlong -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'HahiVana2@Nole' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c1 -a0 -p 'authentication' -C '' '⛄'
|
||||
mpw_expect 'lozwajave' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a0 -p 'identification' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'miy lirfijoja dubu' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a0 -p 'recovery' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'movm bex gevrica jaf' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a0 -p 'recovery' -C 'question' 'masterpasswordapp.com'
|
||||
mpw_expect 'w1!3bA3icmRAc)SS@lwl' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmax -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Fej7]Jug' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tmed -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'wvH7irC1' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tbasic -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'Fej7' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tshort -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect '2117' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tpin -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'fejrajugo' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tname -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'fejr jug gabsibu bax' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tphrase -c1 -a0 -p 'authentication' -C '' 'masterpasswordapp.com'
|
||||
mpw_expect 'QateDojh1@Hecn' -Fnone -u 'Robert Lee Mitchell' -M 'banana colored duckling' -tlong -c4294967295 -a0 -p 'authentication' 'masterpasswordapp.com'
|
||||
|
||||
|
||||
# Finish
|
||||
printf 'Done!\n'
|
||||
exit "$errors"
|
||||
Reference in New Issue
Block a user