2
0

Implement algorithm support for hybrid personal passwords.

This commit is contained in:
Maarten Billemont 2017-08-05 17:33:45 -04:00
parent 228f8e4ed1
commit 322e056661
13 changed files with 400 additions and 38 deletions

171
core/c/base64.c Normal file
View File

@ -0,0 +1,171 @@
/* ====================================================================
* Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED 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 APACHE GROUP OR
* ITS CONTRIBUTORS 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 software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*/
#include "base64.h"
/* aaaack but it's fast and const should make it shared text page. */
static const unsigned char pr2six[256] =
{
/* ASCII table */
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
size_t Base64decode_len(const char *bufcoded) {
size_t nbytesdecoded;
register const unsigned char *bufin;
register int nprbytes;
bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (int)(bufin - (const unsigned char *)bufcoded) - 1;
nbytesdecoded = (size_t)(((nprbytes + 3) / 4) * 3);
return nbytesdecoded;
}
int Base64decode(uint8_t *bufplain, const char *bufcoded) {
int nbytesdecoded;
register const unsigned char *bufin;
register unsigned char *bufout;
register int nprbytes;
bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (int)(bufin - (const unsigned char *)bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
bufout = bufplain;
bufin = (const unsigned char *)bufcoded;
while (nprbytes > 4) {
*(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
if (nprbytes > 1) {
*(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
}
if (nprbytes > 2) {
*(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
}
if (nprbytes > 3) {
*(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
}
nbytesdecoded -= (4 - nprbytes) & 3;
return nbytesdecoded;
}
static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t Base64encode_len(size_t len) {
return ((len + 2) / 3 * 4);
}
int Base64encode(char *encoded, const uint8_t *string, size_t len) {
int i;
char *p;
p = encoded;
for (i = 0; i < len - 2; i += 3) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
*p++ = basis_64[((string[i] & 0x3) << 4) |
((string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
((string[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[string[i + 2] & 0x3F];
}
if (i < len) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
if (i == (len - 1)) {
*p++ = basis_64[((string[i] & 0x3) << 4)];
*p++ = '=';
}
else {
*p++ = basis_64[((string[i] & 0x3) << 4) |
((string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
return (int)(p - encoded);
}

64
core/c/base64.h Normal file
View File

@ -0,0 +1,64 @@
/* ====================================================================
* Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED 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 APACHE GROUP OR
* ITS CONTRIBUTORS 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 software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*/
#include <stddef.h>
#include <stdint.h>
size_t Base64decode_len(const char *bufcoded);
int Base64decode(uint8_t *bufplain, const char *bufcoded);
size_t Base64encode_len(size_t len);
int Base64encode(char *encoded, const uint8_t *string, size_t len);

View File

@ -22,6 +22,7 @@
#include "mpw-types.h"
#include "mpw-util.h"
#include "base64.h"
#define MP_N 32768
#define MP_r 8
@ -155,11 +156,38 @@ static const char *mpw_sitePassword_v0(
const char *mpw_encrypt_v0(
MPMasterKey masterKey, const char *plainText) {
return NULL; // TODO: aes128_cbc
// Encrypt
dbg( "-- encrypting plainText: %s\n", plainText );
size_t bufSize = strlen( plainText );
const uint8_t *cipherBuf = mpw_aes_encrypt( masterKey, MPMasterKeySize, (const uint8_t *)plainText, bufSize );
dbg( "-- cipherBuf: %lu bytes = ", bufSize );
printb( cipherBuf, bufSize );
// Base64-encode
char *cipherText = calloc( 1, Base64encode_len( bufSize ) + 1 );
Base64encode( cipherText, cipherBuf, bufSize );
dbg( "-- b64 encoded -> cipherText: %s\n", cipherText );
mpw_free( cipherBuf, bufSize );
return cipherText;
}
const char *mpw_decrypt_v0(
MPMasterKey masterKey, const char *cipherText) {
return NULL; // TODO: aes128_cbc
// Base64-decode
dbg( "-- decrypting cipherText: %s\n", cipherText );
size_t bufSize = Base64decode_len( cipherText ) + 1;
uint8_t *cipherBuf = calloc( 1, bufSize );
Base64decode( cipherBuf, cipherText );
dbg( "-- b64 decoded: %lu bytes = ", bufSize );
printb( cipherBuf, bufSize );
// Decrypt
const char *plainText = (const char *)mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize );
dbg( "-- decrypted -> plainText: %s\n", plainText );
mpw_free( cipherBuf, bufSize );
return plainText;
}

View File

@ -136,11 +136,11 @@ static const char *mpw_sitePassword_v1(
const char *mpw_encrypt_v1(
MPMasterKey masterKey, const char *plainText) {
return NULL; // TODO: aes128_cbc
return mpw_encrypt_v0( masterKey, plainText );
}
const char *mpw_decrypt_v1(
MPMasterKey masterKey, const char *cipherText) {
return NULL; // TODO: aes128_cbc
return mpw_decrypt_v0( masterKey, cipherText );
}

View File

@ -136,11 +136,11 @@ static const char *mpw_sitePassword_v2(
const char *mpw_encrypt_v2(
MPMasterKey masterKey, const char *plainText) {
return NULL; // TODO: aes128_cbc
return mpw_encrypt_v1( masterKey, plainText );
}
const char *mpw_decrypt_v2(
MPMasterKey masterKey, const char *cipherText) {
return NULL; // TODO: aes128_cbc
return mpw_decrypt_v1( masterKey, cipherText );
}

View File

@ -136,11 +136,11 @@ static const char *mpw_sitePassword_v3(
const char *mpw_encrypt_v3(
MPMasterKey masterKey, const char *plainText) {
return NULL; // TODO: aes128_cbc
return mpw_encrypt_v2( masterKey, plainText );
}
const char *mpw_decrypt_v3(
MPMasterKey masterKey, const char *cipherText) {
return NULL; // TODO: aes128_cbc
return mpw_decrypt_v2( masterKey, cipherText );
}

View File

@ -57,7 +57,7 @@ json_object *mpw_get_json_section(
char *sectionTokenizer = strdup( section ), *sectionToken = sectionTokenizer;
for (sectionToken = strtok( sectionToken, "." ); sectionToken; sectionToken = strtok( NULL, "." ))
if (!json_object_object_get_ex( json_value, sectionToken, &json_value ) || !json_value) {
dbg( "While resolving: %s: Missing value for: %s\n", section, sectionToken );
trc( "While resolving: %s: Missing value for: %s\n", section, sectionToken );
json_value = NULL;
break;
}

View File

@ -55,7 +55,8 @@ MPMarshalledSite *mpw_marshall_site(
realloc( marshalledUser->sites, sizeof( MPMarshalledSite ) * (++marshalledUser->sites_count) )))
return NULL;
marshalledUser->sites[marshalledUser->sites_count - 1] = (MPMarshalledSite){
MPMarshalledSite *site = &marshalledUser->sites[marshalledUser->sites_count - 1];
*site = (MPMarshalledSite){
.name = strdup( siteName ),
.content = NULL,
.type = siteType,
@ -72,7 +73,7 @@ MPMarshalledSite *mpw_marshall_site(
.questions_count = 0,
.questions = NULL,
};
return marshalledUser->sites + sizeof( MPMarshalledSite ) * (marshalledUser->sites_count - 1);
return site;
};
MPMarshalledQuestion *mpw_marshal_question(
@ -82,10 +83,11 @@ MPMarshalledQuestion *mpw_marshal_question(
realloc( marshalledSite->questions, sizeof( MPMarshalledQuestion ) * (++marshalledSite->questions_count) )))
return NULL;
marshalledSite->questions[marshalledSite->questions_count - 1] = (MPMarshalledQuestion){
MPMarshalledQuestion *question = &marshalledSite->questions[marshalledSite->questions_count - 1];
*question = (MPMarshalledQuestion){
.keyword = strdup( keyword ),
};
return marshalledSite->questions + sizeof( MPMarshalledSite ) * (marshalledSite->questions_count - 1);
return question;
}
bool mpw_marshal_free(
@ -130,9 +132,9 @@ static bool mpw_marshall_write_flat(
mpw_string_pushf( out, "# Master Password site export\n" );
if (user->redacted)
mpw_string_pushf( out, "# Export of site names and passwords in clear-text.\n" );
else
mpw_string_pushf( out, "# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n" );
else
mpw_string_pushf( out, "# Export of site names and passwords in clear-text.\n" );
mpw_string_pushf( out, "# \n" );
mpw_string_pushf( out, "##\n" );
mpw_string_pushf( out, "# Format: %d\n", 1 );
@ -161,6 +163,7 @@ static bool mpw_marshall_write_flat(
const char *content = NULL;
if (!user->redacted) {
// Clear Text
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site.algorithm, user->name, user->masterPassword )) {
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
return false;
@ -174,6 +177,7 @@ static bool mpw_marshall_write_flat(
else if (site.type & MPSiteFeatureExportContent && site.content && strlen( site.content ))
content = mpw_decrypt( masterKey, site.content, site.algorithm );
} else if (site.type & MPSiteFeatureExportContent && site.content && strlen( site.content ))
// Redacted
content = strdup( site.content );
if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site.lastUsed ) ))
@ -242,6 +246,7 @@ static bool mpw_marshall_write_json(
const char *content = NULL;
if (!user->redacted) {
// Clear Text
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site.algorithm, user->name, user->masterPassword )) {
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
return false;
@ -256,6 +261,7 @@ static bool mpw_marshall_write_json(
content = mpw_decrypt( masterKey, site.content, site.algorithm );
}
else if (site.type & MPSiteFeatureExportContent && site.content && strlen( site.content ))
// Redacted
content = strdup( site.content );
json_object *json_site = json_object_new_object();
@ -284,6 +290,7 @@ static bool mpw_marshall_write_json(
json_object_object_add( json_site_questions, question.keyword, json_site_question );
if (!user->redacted) {
// Clear Text
MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, 1, MPKeyPurposeRecovery, question.keyword, site.algorithm );
const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site.algorithm );
mpw_free( siteKey, MPSiteKeySize );
@ -500,7 +507,8 @@ static MPMarshalledUser *mpw_marshall_read_flat(
site->uses = (unsigned int)atoi( str_uses );
site->lastUsed = siteLastUsed;
if (siteContent && strlen( siteContent )) {
if (user->redacted) {
if (!user->redacted) {
// Clear Text
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
return NULL;
@ -509,6 +517,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
site->content = mpw_encrypt( masterKey, siteContent, site->algorithm );
}
else
// Redacted
site->content = strdup( siteContent );
}
}
@ -653,7 +662,8 @@ static MPMarshalledUser *mpw_marshall_read_json(
site->uses = siteUses;
site->lastUsed = siteLastUsed;
if (siteContent && strlen( siteContent )) {
if (user->redacted) {
if (!user->redacted) {
// Clear Text
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
return NULL;
@ -662,6 +672,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
site->content = mpw_encrypt( masterKey, siteContent, site->algorithm );
}
else
// Redacted
site->content = strdup( siteContent );
}

View File

@ -30,6 +30,9 @@
#include <scrypt/sha256.h>
#elif HAS_SODIUM
#include "sodium.h"
#ifdef SODIUM_LIBRARY_MINIMAL
#include "crypto_stream_aes128ctr.h"
#endif
#endif
#include "mpw-util.h"
@ -67,6 +70,9 @@ bool mpw_push_string(uint8_t **const buffer, size_t *const bufferSize, const cha
bool mpw_string_push(char **const string, const char *pushString) {
if (!*string)
*string = calloc( 1, sizeof( char ) );
size_t stringLength = strlen( *string );
return pushString && mpw_push_buf( (uint8_t **const)string, &stringLength, pushString, strlen( pushString ) + 1 );
}
@ -123,37 +129,79 @@ uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_
mpw_free( key, keySize );
return NULL;
}
#else
#error No crypto support for mpw_scrypt.
#endif
return key;
}
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *message, const size_t messageSize) {
#if HAS_CPERCIVA
uint8_t *const buffer = malloc( 32 );
if (!buffer)
if (!key || !keySize || !message || !messageSize)
return NULL;
HMAC_SHA256_Buf( key, keySize, salt, saltSize, buffer );
return buffer;
#if HAS_CPERCIVA
uint8_t *const mac = malloc( 32 );
if (!mac)
return NULL;
HMAC_SHA256_Buf( key, keySize, message, messageSize, mac );
#elif HAS_SODIUM
uint8_t *const buffer = malloc( crypto_auth_hmacsha256_BYTES );
if (!buffer)
uint8_t *const mac = malloc( crypto_auth_hmacsha256_BYTES );
if (!mac)
return NULL;
crypto_auth_hmacsha256_state state;
if (crypto_auth_hmacsha256_init( &state, key, keySize ) != 0 ||
crypto_auth_hmacsha256_update( &state, salt, saltSize ) != 0 ||
crypto_auth_hmacsha256_final( &state, buffer ) != 0) {
mpw_free( buffer, crypto_auth_hmacsha256_BYTES );
crypto_auth_hmacsha256_update( &state, message, messageSize ) != 0 ||
crypto_auth_hmacsha256_final( &state, mac ) != 0) {
mpw_free( mac, crypto_auth_hmacsha256_BYTES );
return NULL;
}
return buffer;
#else
#error No crypto support for mpw_hmac_sha256.
#endif
return mac;
}
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 (!key || keySize < crypto_stream_KEYBYTES)
return NULL;
uint8_t cipherKey[crypto_stream_KEYBYTES];
memcpy( cipherKey, key, sizeof( cipherKey ) );
uint8_t nonce[crypto_stream_NONCEBYTES];
bzero( (void *)nonce, sizeof( nonce ) );
if (encrypt) {
uint8_t *const cipherBuf = malloc( bufSize );
crypto_stream_aes128ctr_xor( cipherBuf, buf, bufSize, nonce, cipherKey );
return cipherBuf;
} else {
uint8_t *const plainBuf = malloc( bufSize );
crypto_stream_aes128ctr( plainBuf, bufSize, nonce, cipherKey );
for (size_t c = 0; c < bufSize; ++c)
plainBuf[c] = buf[c] ^ plainBuf[c];
return plainBuf;
}
#else
#error No crypto support for mpw_aes.
#endif
}
uint8_t const *mpw_aes_encrypt(const uint8_t *key, const size_t keySize, const uint8_t *plainBuf, const size_t bufSize) {
return mpw_aes( true, key, keySize, plainBuf, bufSize );
}
uint8_t const *mpw_aes_decrypt(const uint8_t *key, const size_t keySize, const uint8_t *cipherBuf, const size_t bufSize) {
return mpw_aes( false, key, keySize, cipherBuf, bufSize );
}
MPKeyID mpw_id_buf(const void *buf, size_t length) {
@ -167,6 +215,8 @@ MPKeyID mpw_id_buf(const void *buf, size_t length) {
#elif HAS_SODIUM
uint8_t hash[crypto_hash_sha256_BYTES];
crypto_hash_sha256( hash, buf, length );
#else
#error No crypto support for mpw_id_buf.
#endif
return mpw_hex( hash, sizeof( hash ) / sizeof( uint8_t ) );
@ -325,3 +375,10 @@ const size_t mpw_utf8_strlen(const char *utf8String) {
return charlen;
}
void printb(const void *p, size_t size) {
for (int i = 0; i < size; ++i)
dbg( "%02hhX ", ((const uint8_t *)p)[i] );
dbg( "\n" );
}

View File

@ -121,15 +121,23 @@ bool mpw_free_string(
//// Cryptographic functions.
/** Perform a scrypt-based key derivation on the given key using the given salt and scrypt parameters.
* @return A new keySize-size allocated buffer. */
/** Derive a key from the given secret and salt using the scrypt KDF.
* @return A new keySize allocated buffer containing the key. */
uint8_t const *mpw_scrypt(
const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
uint64_t N, uint32_t r, uint32_t p);
/** Calculate a SHA256-based HMAC by encrypting the given salt with the given key.
* @return A new 32-byte allocated buffer. */
/** Calculate the MAC for the given message with the given key using SHA256-HMAC.
* @return A new 32-byte allocated buffer containing the MAC. */
uint8_t const *mpw_hmac_sha256(
const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize);
/** Encrypt a plainBuf with the given key using AES-128-CBC.
* @return A new bufSize allocated buffer containing the cipherBuf. */
uint8_t const *mpw_aes_encrypt(
const uint8_t *key, const size_t keySize, const uint8_t *plainBuf, const size_t bufSize);
/** Decrypt a cipherBuf with the given key using AES-128-CBC.
* @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);
//// Visualizers.
@ -155,4 +163,6 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword);
/** @return The amount of display characters in the given UTF-8 string. */
const size_t mpw_utf8_strlen(const char *utf8String);
void printb(const void *p, size_t size);
#endif // _MPW_UTIL_H

View File

@ -182,6 +182,7 @@
DA5A09E0171A70E4005284AB /* play@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09DE171A70E4005284AB /* play@2x.png */; };
DA5A09EA171BB0F7005284AB /* unlocked.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09E8171BB0F7005284AB /* unlocked.png */; };
DA5A09EB171BB0F7005284AB /* unlocked@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09E9171BB0F7005284AB /* unlocked@2x.png */; };
DA5B0B401F36469400B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B3E1F36469400B663F0 /* base64.c */; };
DA5BFA49147E415C00F98B1E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA48147E415C00F98B1E /* UIKit.framework */; };
DA5BFA4B147E415C00F98B1E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DA5BFA4D147E415C00F98B1E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */; };
@ -785,6 +786,8 @@
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>"; };
DA5A09E9171BB0F7005284AB /* unlocked@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unlocked@2x.png"; sourceTree = "<group>"; };
DA5B0B3E1F36469400B663F0 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; };
DA5B0B3F1F36469400B663F0 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = "<group>"; };
DA5BFA44147E415C00F98B1E /* MasterPassword.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MasterPassword.app; sourceTree = BUILT_PRODUCTS_DIR; };
DA5BFA48147E415C00F98B1E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@ -1719,6 +1722,8 @@
93D39A2239FFFE6BEC83E191 /* C */ = {
isa = PBXGroup;
children = (
DA5B0B3E1F36469400B663F0 /* base64.c */,
DA5B0B3F1F36469400B663F0 /* base64.h */,
93D390A99850139D0FF0211E /* mpw-algorithm_v0.c */,
93D396F918E6470DB846C17F /* mpw-algorithm_v1.c */,
93D390A3B351FEF1B9EDAB56 /* mpw-algorithm_v2.c */,
@ -3905,6 +3910,7 @@
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */,
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */,
DA5B0B401F36469400B663F0 /* base64.c in Sources */,
93D39577FD8BB0945DB2F0A3 /* MPAlgorithmV3.m in Sources */,
93D39E5F7F6D7F5C0FAD090F /* MPTypes.m in Sources */,
DA0CC58C1EB6B030009A8ED9 /* MPGeneratedSiteEntity+CoreDataClass.m in Sources */,

View File

@ -83,6 +83,10 @@
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE931A7D8117003E5423 /* MPTypes.m */; };
DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */; };
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */; };
DA5B0B3A1F36467300B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
DA5B0B3B1F36467800B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
DA5B0B3C1F36467900B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
DA5B0B3D1F36467900B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C981724A667003798D8 /* MPAlgorithm.m */; };
DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9A1724A667003798D8 /* MPAlgorithmV0.m */; };
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */; };
@ -456,6 +460,8 @@
DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV2.m; sourceTree = "<group>"; };
DA5180CC19FF307E00A587E9 /* MPAppDelegate_Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_Store.h; sourceTree = "<group>"; };
DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Store.m; sourceTree = "<group>"; };
DA5B0B381F36467300B663F0 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; };
DA5B0B391F36467300B663F0 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = "<group>"; };
DA5BFA44147E415C00F98B1E /* Master Password.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Master Password.app"; sourceTree = BUILT_PRODUCTS_DIR; };
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@ -1809,6 +1815,8 @@
DA6773291A4746AF004F356A /* C */ = {
isa = PBXGroup;
children = (
DA5B0B381F36467300B663F0 /* base64.c */,
DA5B0B391F36467300B663F0 /* base64.h */,
DA1C7AB71F1A8F6E009A3551 /* cli */,
DA831A271A6E1146000AC234 /* mpw-algorithm_v0.c */,
DA831A281A6E1146000AC234 /* mpw-algorithm_v1.c */,
@ -2528,6 +2536,7 @@
files = (
DA1C7AAA1F1A8F24009A3551 /* mpw-marshall.c in Sources */,
DA1C7AAB1F1A8F24009A3551 /* mpw-types.c in Sources */,
DA5B0B3D1F36467900B663F0 /* base64.c in Sources */,
DA1C7AAC1F1A8F24009A3551 /* mpw-util.c in Sources */,
DA1C7AC31F1A8FBA009A3551 /* mpw-cli.c in Sources */,
DA7471A31F2B71AE005F3468 /* mpw-marshall-util.c in Sources */,
@ -2539,6 +2548,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DA5B0B3C1F36467900B663F0 /* base64.c in Sources */,
DA1C7ACA1F1A8FD8009A3551 /* mpw-types.c in Sources */,
DA1C7ACB1F1A8FD8009A3551 /* mpw-util.c in Sources */,
DA1C7AD71F1A8FE6009A3551 /* mpw-bench.c in Sources */,
@ -2566,6 +2576,7 @@
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */,
DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */,
DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */,
DA5B0B3A1F36467300B663F0 /* base64.c in Sources */,
DA26861F1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m in Sources */,
DA3B8456190FC89700246EEA /* MPFixable.m in Sources */,
DA5E5D001724A667003798D8 /* MPEntities.m in Sources */,
@ -2602,6 +2613,7 @@
DA6774451A474A3B004F356A /* mpw-types.c in Sources */,
DA6774461A474A3B004F356A /* mpw-util.c in Sources */,
DA1C7AD91F1A8FF4009A3551 /* mpw-tests.c in Sources */,
DA5B0B3B1F36467800B663F0 /* base64.c in Sources */,
DA6774431A474A3B004F356A /* mpw-algorithm.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -259,12 +259,13 @@ mpw() {
(( 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/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" "core/mpw-marshall-util.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"
}
@ -299,10 +300,11 @@ mpw-bench() {
-l"crypto"
)
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/mpw-algorithm.o" "core/mpw-types.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"
}
@ -331,11 +333,12 @@ mpw-tests() {
-l"crypto" -l"xml2"
)
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/mpw-algorithm.o" "core/mpw-types.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-tests-util.o" "cli/mpw-tests.c" -o "mpw-tests"
echo "done! Now use ./mpw-tests"
}