diff --git a/MasterPassword/C/mpw-algorithm.c b/MasterPassword/C/mpw-algorithm.c index dca0a0ea..9f6471c8 100644 --- a/MasterPassword/C/mpw-algorithm.c +++ b/MasterPassword/C/mpw-algorithm.c @@ -13,11 +13,11 @@ #include "mpw-types.h" #include "mpw-util.h" +#include "mpw-algorithm.h" #define MP_N 32768 #define MP_r 8 #define MP_p 2 -#define MP_dkLen 64 #define MP_hash PearlHashSHA256 const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword) { @@ -34,16 +34,20 @@ const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPass mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope ); mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( strlen( fullName ) ) ); mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName ); - if (!masterKeySalt) + if (!masterKeySalt) { ftl( "Could not allocate master key salt: %d\n", errno ); + return NULL; + } trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) ); // Calculate the master key. // masterKey = scrypt( masterPassword, masterKeySalt ) const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); mpw_free( masterKeySalt, masterKeySaltSize ); - if (!masterKey) + if (!masterKey) { ftl( "Could not allocate master key: %d\n", errno ); + return NULL; + } trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) ); return masterKey; @@ -71,20 +75,28 @@ const char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName, mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) ); mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext ); } - if (!sitePasswordInfo) + if (!sitePasswordInfo) { ftl( "Could not allocate site seed info: %d\n", errno ); + return NULL; + } trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) ); const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize ); - if (!sitePasswordSeed) + mpw_free( sitePasswordInfo, sitePasswordInfoSize ); + if (!sitePasswordSeed) { ftl( "Could not allocate site seed: %d\n", errno ); + return NULL; + } trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) ); // Determine the template. const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] ); trc( "type %d, template: %s\n", siteType, template ); - if (strlen( template ) > 32) + if (strlen( template ) > 32) { ftl( "Template too long for password seed: %lu", strlen( template ) ); + mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) ); + return NULL; + } // Encode the password from the seed using the template. char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) ); diff --git a/MasterPassword/C/mpw-algorithm.h b/MasterPassword/C/mpw-algorithm.h index 33f3ce93..ac080a93 100644 --- a/MasterPassword/C/mpw-algorithm.h +++ b/MasterPassword/C/mpw-algorithm.h @@ -6,13 +6,15 @@ // Copyright (c) 2014 Lyndir. All rights reserved. // +#define MP_dkLen 64 + /** Derive the master key for a user based on their name and master password. - * @return A new 64-byte allocated buffer. */ + * @return A new MP_dkLen-byte allocated buffer or NULL if an allocation error occurred. */ const uint8_t *mpw_masterKeyForUser( const char *fullName, const char *masterPassword); /** Encode a password for the site from the given master key and site parameters. - * @return A newly allocated string. */ + * @return A newly allocated string or NULL if an allocation error occurred. */ const char *mpw_passwordForSite( const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, const MPSiteVariant siteVariant, const char *siteContext); diff --git a/MasterPassword/C/mpw-cli.c b/MasterPassword/C/mpw-cli.c index b45c2ff1..0aee2a41 100644 --- a/MasterPassword/C/mpw-cli.c +++ b/MasterPassword/C/mpw-cli.c @@ -190,9 +190,14 @@ int main(int argc, char *const argv[]) { // Output the password. const uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword ); mpw_free( masterPassword, strlen( masterPassword ) ); + if (!masterKey) + ftl( "Couldn't derive master key." ); const char *sitePassword = mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString ); - fprintf( stdout, "%s\n", sitePassword ); + mpw_free( masterKey, MP_dkLen ); + if (!sitePassword) + ftl( "Couldn't derive site password." ); + fprintf( stdout, "%s\n", sitePassword ); return 0; } diff --git a/MasterPassword/C/mpw-util.c b/MasterPassword/C/mpw-util.c index cb9f0638..be7864c0 100644 --- a/MasterPassword/C/mpw-util.c +++ b/MasterPassword/C/mpw-util.c @@ -18,12 +18,16 @@ void mpw_pushBuf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) { if (*bufferSize == (size_t)-1) + // The buffer was marked as broken, it is missing a previous push. Abort to avoid corrupt content. return; *bufferSize += pushSize; - *buffer = realloc( *buffer, *bufferSize ); - if (!*buffer) { + uint8_t **const resizedBuffer = realloc( *buffer, *bufferSize ); + if (!resizedBuffer) { + // realloc failed, we can't push. Mark the buffer as broken. + mpw_free( *buffer, *bufferSize - pushSize ); *bufferSize = -1; + *buffer = NULL; return; }