From 68d1ab58b7d7188d71fd2309fd656f1dc4a36b55 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Sun, 6 Aug 2017 11:40:10 -0400 Subject: [PATCH] De-duplicate algorithm implementations and improve trace output. --- core/c/mpw-algorithm.c | 22 ++++++-- core/c/mpw-algorithm_v0.c | 66 ++++++++++------------- core/c/mpw-algorithm_v1.c | 104 +++++++++--------------------------- core/c/mpw-algorithm_v2.c | 98 ++++++++++------------------------ core/c/mpw-algorithm_v3.c | 108 +++++++++++--------------------------- core/c/mpw-util.c | 1 - 6 files changed, 127 insertions(+), 272 deletions(-) diff --git a/core/c/mpw-algorithm.c b/core/c/mpw-algorithm.c index 35d4dd18..8db80b71 100644 --- a/core/c/mpw-algorithm.c +++ b/core/c/mpw-algorithm.c @@ -24,18 +24,21 @@ MPMasterKey mpw_masterKey(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) { + trc( "-- mpw_masterKey (algorithm: %u)\n", algorithmVersion ); + trc( "fullName: %s\n", fullName ); + trc( "masterPassword.id: %s\n", mpw_id_buf( masterPassword, strlen( masterPassword ) ) ); if (!fullName || !masterPassword) return NULL; switch (algorithmVersion) { case MPAlgorithmVersion0: - return mpw_masterKeyForUser_v0( fullName, masterPassword ); + return mpw_masterKey_v0( fullName, masterPassword ); case MPAlgorithmVersion1: - return mpw_masterKeyForUser_v1( fullName, masterPassword ); + return mpw_masterKey_v1( fullName, masterPassword ); case MPAlgorithmVersion2: - return mpw_masterKeyForUser_v2( fullName, masterPassword ); + return mpw_masterKey_v2( fullName, masterPassword ); case MPAlgorithmVersion3: - return mpw_masterKeyForUser_v3( fullName, masterPassword ); + return mpw_masterKey_v3( fullName, masterPassword ); default: err( "Unsupported version: %d\n", algorithmVersion ); return NULL; @@ -46,6 +49,11 @@ MPSiteKey mpw_siteKey( MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) { + trc( "-- mpw_siteKey (algorithm: %u)\n", algorithmVersion ); + trc( "siteName: %s\n", siteName ); + trc( "siteCounter: %d\n", siteCounter ); + trc( "keyPurpose: %d (%s)\n", keyPurpose, mpw_nameForPurpose( keyPurpose ) ); + trc( "keyContext: %s\n", keyContext ); if (!masterKey || !siteName) return NULL; @@ -67,6 +75,8 @@ MPSiteKey mpw_siteKey( const char *mpw_sitePassword( MPSiteKey siteKey, const MPPasswordType passwordType, const MPAlgorithmVersion algorithmVersion) { + trc( "-- mpw_sitePassword (algorithm: %u)\n", algorithmVersion ); + trc( "passwordType: %d (%s)\n", passwordType, mpw_nameForType( passwordType ) ); if (!siteKey) return NULL; @@ -88,6 +98,8 @@ const char *mpw_sitePassword( const char *mpw_encrypt( MPMasterKey masterKey, const char *plainText, const MPAlgorithmVersion algorithmVersion) { + trc( "-- mpw_encrypt (algorithm: %u)\n", algorithmVersion ); + trc( "plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) ); if (!masterKey || !plainText) return NULL; @@ -109,6 +121,8 @@ const char *mpw_encrypt( const char *mpw_decrypt( MPMasterKey masterKey, const char *cipherText, const MPAlgorithmVersion algorithmVersion) { + trc( "-- mpw_decrypt (algorithm: %u)\n", algorithmVersion ); + trc( "cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) ); if (!masterKey || !cipherText) return NULL; diff --git a/core/c/mpw-algorithm_v0.c b/core/c/mpw-algorithm_v0.c index ca293ffc..fdcbee92 100644 --- a/core/c/mpw-algorithm_v0.c +++ b/core/c/mpw-algorithm_v0.c @@ -24,10 +24,11 @@ #include "mpw-util.h" #include "base64.h" -#define MP_N 32768 -#define MP_r 8 -#define MP_p 2 +#define MP_N 32768LU +#define MP_r 8U +#define MP_p 2U +// Algorithm version helpers. static const char *mpw_templateForType_v0(MPPasswordType type, uint16_t seedByte) { size_t count = 0; @@ -46,36 +47,36 @@ static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedBy return classCharacters[seedByte % strlen( classCharacters )]; } -static MPMasterKey mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) { +// Algorithm version overrides. +static MPMasterKey mpw_masterKey_v0( + const char *fullName, const char *masterPassword) { - const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); - trc( "algorithm: v%d\n", 0 ); - trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) ); - trc( "masterPassword: %s\n", masterPassword ); - trc( "key scope: %s\n", mpKeyScope ); + const char *keyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); + trc( "keyScope: %s\n", keyScope ); // Calculate the master key salt. - // masterKeySalt = mpKeyScope . #fullName . fullName + trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s\n", + keyScope, mpw_hex_l( htonl( mpw_utf8_strlen( fullName ) ) ), fullName ); size_t masterKeySaltSize = 0; uint8_t *masterKeySalt = NULL; - mpw_push_string( &masterKeySalt, &masterKeySaltSize, mpKeyScope ); + mpw_push_string( &masterKeySalt, &masterKeySaltSize, keyScope ); mpw_push_int( &masterKeySalt, &masterKeySaltSize, htonl( mpw_utf8_strlen( fullName ) ) ); mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName ); if (!masterKeySalt) { err( "Could not allocate master key salt: %s\n", strerror( errno ) ); return NULL; } - trc( "masterKeySalt ID: %s\n", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); + trc( " => masterKeySalt.id: %s\n", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); // Calculate the master key. - // masterKey = scrypt( masterPassword, masterKeySalt ) - const uint8_t *masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); + trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", MP_N, MP_r, MP_p ); + MPMasterKey masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); mpw_free( masterKeySalt, masterKeySaltSize ); if (!masterKey) { err( "Could not allocate master key: %s\n", strerror( errno ) ); return NULL; } - trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); + trc( " => masterKey.id: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); return masterKey; } @@ -85,18 +86,12 @@ static MPSiteKey mpw_siteKey_v0( const MPKeyPurpose keyPurpose, const char *keyContext) { const char *keyScope = mpw_scopeForPurpose( keyPurpose ); - trc( "-- mpw_siteKey_v0\n" ); - trc( "siteName: %s\n", siteName ); - trc( "siteCounter: %d\n", siteCounter ); - trc( "keyPurpose: %d\n", keyPurpose ); - trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "": keyContext ); - trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", - keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, - mpw_hex_l( htonl( siteCounter ) ), - mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext ); + trc( "keyScope: %s\n", keyScope ); // Calculate the site seed. - // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . keyContext ) + 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 ); size_t siteSaltSize = 0; uint8_t *siteSalt = NULL; mpw_push_string( &siteSalt, &siteSaltSize, keyScope ); @@ -112,15 +107,17 @@ static MPSiteKey mpw_siteKey_v0( mpw_free( siteSalt, siteSaltSize ); return NULL; } - trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); + trc( " => siteSalt.id: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); + trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n", + mpw_id_buf( masterKey, MPMasterKeySize ) ); MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); mpw_free( siteSalt, siteSaltSize ); if (!siteKey) { err( "Could not allocate site key: %s\n", strerror( errno ) ); return NULL; } - trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); + trc( " => siteKey.id: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); return siteKey; } @@ -128,13 +125,10 @@ static MPSiteKey mpw_siteKey_v0( static const char *mpw_sitePassword_v0( MPSiteKey siteKey, const MPPasswordType passwordType) { - trc( "-- mpw_sitePassword_v0\n" ); - trc( "passwordType: %d\n", passwordType ); - // Determine the template. const char *_siteKey = (const char *)siteKey; const char *template = mpw_templateForType_v0( passwordType, htons( _siteKey[0] ) ); - trc( "type %d, template: %s\n", passwordType, template ); + trc( "template: %u => %s\n", htons( _siteKey[0] ), template ); if (!template) return NULL; if (strlen( template ) > MPSiteKeySize) { @@ -146,9 +140,10 @@ static const char *mpw_sitePassword_v0( 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] ) ); - trc( "class %c, index %u (0x%02X) -> character: %c\n", + trc( " - class: %c, index: %5u (0x%02hX) => character: %c\n", template[c], htons( _siteKey[c + 1] ), htons( _siteKey[c + 1] ), sitePassword[c] ); } + trc( " => password: %s\n", sitePassword ); return sitePassword; } @@ -156,9 +151,6 @@ static const char *mpw_sitePassword_v0( const char *mpw_encrypt_v0( MPMasterKey masterKey, const char *plainText) { - trc( "-- mpw_encrypt_v0\n" ); - trc( "plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) ); - // Encrypt size_t bufSize = strlen( plainText ); const uint8_t *cipherBuf = mpw_aes_encrypt( masterKey, MPMasterKeySize, (const uint8_t *)plainText, bufSize ); @@ -168,7 +160,6 @@ const char *mpw_encrypt_v0( } trc( "cipherBuf: %lu bytes = %s\n", bufSize, mpw_hex( cipherBuf, bufSize ) ); - // Base64-encode size_t b64Max = mpw_base64_encode_max( bufSize ); char *cipherText = calloc( 1, b64Max + 1 ); @@ -186,9 +177,6 @@ const char *mpw_encrypt_v0( const char *mpw_decrypt_v0( MPMasterKey masterKey, const char *cipherText) { - trc( "-- mpw_decrypt_v0\n" ); - trc( "cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) ); - // Base64-decode size_t bufSize = mpw_base64_decode_max( cipherText ); uint8_t *cipherBuf = calloc( 1, bufSize ); diff --git a/core/c/mpw-algorithm_v1.c b/core/c/mpw-algorithm_v1.c index 5bbb36e3..790d462c 100644 --- a/core/c/mpw-algorithm_v1.c +++ b/core/c/mpw-algorithm_v1.c @@ -23,98 +23,41 @@ #include "mpw-types.h" #include "mpw-util.h" -#define MP_N 32768 -#define MP_r 8 -#define MP_p 2 +#define MP_N 32768LU +#define MP_r 8U +#define MP_p 2U -static MPMasterKey mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) { +// Inherited functions. +MPMasterKey mpw_masterKey_v0( + const char *fullName, const char *masterPassword); +MPSiteKey mpw_siteKey_v0( + MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, + const MPKeyPurpose keyPurpose, const char *keyContext); +const char *mpw_encrypt_v0( + MPMasterKey masterKey, const char *plainText); +const char *mpw_decrypt_v0( + MPMasterKey masterKey, const char *cipherText); - const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); - trc( "algorithm: v%d\n", 1 ); - trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) ); - trc( "masterPassword: %s\n", masterPassword ); - trc( "key scope: %s\n", mpKeyScope ); +// Algorithm version overrides. +static MPMasterKey mpw_masterKey_v1( + const char *fullName, const char *masterPassword) { - // Calculate the master key salt. - // masterKeySalt = mpKeyScope . #fullName . fullName - size_t masterKeySaltSize = 0; - uint8_t *masterKeySalt = NULL; - mpw_push_string( &masterKeySalt, &masterKeySaltSize, mpKeyScope ); - mpw_push_int( &masterKeySalt, &masterKeySaltSize, htonl( mpw_utf8_strlen( fullName ) ) ); - mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName ); - if (!masterKeySalt) { - err( "Could not allocate master key salt: %s\n", strerror( errno ) ); - return NULL; - } - trc( "masterKeySalt ID: %s\n", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); - - // Calculate the master key. - // masterKey = scrypt( masterPassword, masterKeySalt ) - MPMasterKey masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); - mpw_free( masterKeySalt, masterKeySaltSize ); - if (!masterKey) { - err( "Could not allocate master key: %s\n", strerror( errno ) ); - return NULL; - } - trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); - - return masterKey; + return mpw_masterKey_v0( fullName, masterPassword ); } static MPSiteKey mpw_siteKey_v1( MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, const MPKeyPurpose keyPurpose, const char *keyContext) { - const char *keyScope = mpw_scopeForPurpose( keyPurpose ); - trc( "-- mpw_siteKey_v1\n" ); - trc( "siteName: %s\n", siteName ); - trc( "siteCounter: %d\n", siteCounter ); - trc( "keyPurpose: %d\n", keyPurpose ); - trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "": keyContext ); - trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", - keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, - mpw_hex_l( htonl( siteCounter ) ), - mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext ); - - // Calculate the site seed. - // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . 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_string( &siteSalt, &siteSaltSize, siteName ); - mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) ); - if (keyContext) { - mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( keyContext ) ) ); - mpw_push_string( &siteSalt, &siteSaltSize, keyContext ); - } - if (!siteSalt || !siteSaltSize) { - 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 ) ); - - MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); - mpw_free( siteSalt, siteSaltSize ); - if (!siteKey) { - err( "Could not allocate site key: %s\n", strerror( errno ) ); - return NULL; - } - trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); - - return siteKey; + return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext ); } static const char *mpw_sitePassword_v1( MPSiteKey siteKey, const MPPasswordType passwordType) { - trc( "-- mpw_sitePassword_v1\n" ); - trc( "passwordType: %d\n", passwordType ); - // Determine the template. const char *template = mpw_templateForType( passwordType, siteKey[0] ); - trc( "type %d, template: %s\n", passwordType, template ); + trc( "template: %u => %s\n", siteKey[0], template ); if (!template) return NULL; if (strlen( template ) > MPSiteKeySize) { @@ -126,20 +69,21 @@ static const char *mpw_sitePassword_v1( 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] ); - trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], siteKey[c + 1], siteKey[c + 1], - sitePassword[c] ); + trc( " - class: %c, index: %3u (0x%02hhX) => character: %c\n", + template[c], siteKey[c + 1], siteKey[c + 1], sitePassword[c] ); } + trc( " => password: %s\n", sitePassword ); return sitePassword; } -const char *mpw_encrypt_v1( +static const char *mpw_encrypt_v1( MPMasterKey masterKey, const char *plainText) { return mpw_encrypt_v0( masterKey, plainText ); } -const char *mpw_decrypt_v1( +static const char *mpw_decrypt_v1( MPMasterKey masterKey, const char *cipherText) { return mpw_decrypt_v0( masterKey, cipherText ); diff --git a/core/c/mpw-algorithm_v2.c b/core/c/mpw-algorithm_v2.c index c0cd6a73..d2351c03 100644 --- a/core/c/mpw-algorithm_v2.c +++ b/core/c/mpw-algorithm_v2.c @@ -23,42 +23,25 @@ #include "mpw-types.h" #include "mpw-util.h" -#define MP_N 32768 -#define MP_r 8 -#define MP_p 2 +#define MP_N 32768LU +#define MP_r 8U +#define MP_p 2U -static MPMasterKey mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) { +// Inherited functions. +MPMasterKey mpw_masterKey_v1( + const char *fullName, const char *masterPassword); +const char *mpw_sitePassword_v1( + MPSiteKey siteKey, const MPPasswordType passwordType); +const char *mpw_encrypt_v1( + MPMasterKey masterKey, const char *plainText); +const char *mpw_decrypt_v1( + MPMasterKey masterKey, const char *cipherText); - const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); - trc( "algorithm: v%d\n", 2 ); - trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) ); - trc( "masterPassword: %s\n", masterPassword ); - trc( "key scope: %s\n", mpKeyScope ); +// Algorithm version overrides. +static MPMasterKey mpw_masterKey_v2( + const char *fullName, const char *masterPassword) { - // Calculate the master key salt. - // masterKeySalt = mpKeyScope . #fullName . fullName - size_t masterKeySaltSize = 0; - uint8_t *masterKeySalt = NULL; - mpw_push_string( &masterKeySalt, &masterKeySaltSize, mpKeyScope ); - mpw_push_int( &masterKeySalt, &masterKeySaltSize, htonl( mpw_utf8_strlen( fullName ) ) ); - mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName ); - if (!masterKeySalt) { - err( "Could not allocate master key salt: %s\n", strerror( errno ) ); - return NULL; - } - trc( "masterKeySalt ID: %s\n", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); - - // Calculate the master key. - // masterKey = scrypt( masterPassword, masterKeySalt ) - const uint8_t *masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); - mpw_free( masterKeySalt, masterKeySaltSize ); - if (!masterKey) { - err( "Could not allocate master key: %s\n", strerror( errno ) ); - return NULL; - } - trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); - - return masterKey; + return mpw_masterKey_v1( fullName, masterPassword ); } static MPSiteKey mpw_siteKey_v2( @@ -66,18 +49,12 @@ static MPSiteKey mpw_siteKey_v2( const MPKeyPurpose keyPurpose, const char *keyContext) { const char *keyScope = mpw_scopeForPurpose( keyPurpose ); - trc( "-- mpw_siteKey_v2\n" ); - trc( "siteName: %s\n", siteName ); - trc( "siteCounter: %d\n", siteCounter ); - trc( "keyPurpose: %d\n", keyPurpose ); - trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "": keyContext ); - trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", - keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, - mpw_hex_l( htonl( siteCounter ) ), - mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext ); + trc( "keyScope: %s\n", keyScope ); // Calculate the site seed. - // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . keyContext ) + 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 ); size_t siteSaltSize = 0; uint8_t *siteSalt = NULL; mpw_push_string( &siteSalt, &siteSaltSize, keyScope ); @@ -93,15 +70,17 @@ static MPSiteKey mpw_siteKey_v2( mpw_free( siteSalt, siteSaltSize ); return NULL; } - trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); + trc( " => siteSalt.id: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); - const uint8_t *siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); + trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n", + mpw_id_buf( masterKey, MPMasterKeySize ) ); + MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); mpw_free( siteSalt, siteSaltSize ); if (!siteKey) { err( "Could not allocate site key: %s\n", strerror( errno ) ); return NULL; } - trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); + trc( " => siteKey.id: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); return siteKey; } @@ -109,37 +88,16 @@ static MPSiteKey mpw_siteKey_v2( static const char *mpw_sitePassword_v2( MPSiteKey siteKey, const MPPasswordType passwordType) { - trc( "-- mpw_sitePassword_v2\n" ); - trc( "passwordType: %d\n", passwordType ); - - // Determine the template. - const char *template = mpw_templateForType( passwordType, siteKey[0] ); - trc( "type %d, template: %s\n", passwordType, template ); - if (!template) - return NULL; - if (strlen( template ) > MPSiteKeySize) { - err( "Template too long for password seed: %lu\n", strlen( template ) ); - return NULL; - } - - // 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] ); - trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], siteKey[c + 1], siteKey[c + 1], - sitePassword[c] ); - } - - return sitePassword; + return mpw_sitePassword_v1( siteKey, passwordType ); } -const char *mpw_encrypt_v2( +static const char *mpw_encrypt_v2( MPMasterKey masterKey, const char *plainText) { return mpw_encrypt_v1( masterKey, plainText ); } -const char *mpw_decrypt_v2( +static const char *mpw_decrypt_v2( MPMasterKey masterKey, const char *cipherText) { return mpw_decrypt_v1( masterKey, cipherText ); diff --git a/core/c/mpw-algorithm_v3.c b/core/c/mpw-algorithm_v3.c index 54e77668..7d2b57e4 100644 --- a/core/c/mpw-algorithm_v3.c +++ b/core/c/mpw-algorithm_v3.c @@ -23,40 +23,51 @@ #include "mpw-types.h" #include "mpw-util.h" -#define MP_N 32768 -#define MP_r 8 -#define MP_p 2 +#define MP_N 32768LU +#define MP_r 8U +#define MP_p 2U -static MPMasterKey mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) { +// Inherited functions. +MPSiteKey mpw_siteKey_v2( + MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, + const MPKeyPurpose keyPurpose, const char *keyContext); +const char *mpw_sitePassword_v2( + MPSiteKey siteKey, const MPPasswordType passwordType); +const char *mpw_encrypt_v2( + MPMasterKey masterKey, const char *plainText); +const char *mpw_decrypt_v2( + MPMasterKey masterKey, const char *cipherText); - const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); - trc( "-- mpw_masterKeyForUser_v3\n" ); - trc( "fullName: %s (%zu)\n", fullName, strlen( fullName ) ); - trc( "masterPassword: %s\n", masterPassword ); - trc( "key scope: %s\n", mpKeyScope ); +// Algorithm version overrides. +static MPMasterKey mpw_masterKey_v3( + const char *fullName, const char *masterPassword) { + + const char *keyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); + trc( "keyScope: %s\n", keyScope ); // Calculate the master key salt. - // masterKeySalt = mpKeyScope . #fullName . fullName + trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s\n", + keyScope, mpw_hex_l( htonl( strlen( fullName ) ) ), fullName ); size_t masterKeySaltSize = 0; uint8_t *masterKeySalt = NULL; - mpw_push_string( &masterKeySalt, &masterKeySaltSize, mpKeyScope ); + mpw_push_string( &masterKeySalt, &masterKeySaltSize, keyScope ); mpw_push_int( &masterKeySalt, &masterKeySaltSize, htonl( strlen( fullName ) ) ); mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName ); if (!masterKeySalt) { err( "Could not allocate master key salt: %s\n", strerror( errno ) ); return NULL; } - trc( "masterKeySalt ID: %s\n", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); + trc( " => masterKeySalt.id: %s\n", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); // Calculate the master key. - // masterKey = scrypt( masterPassword, masterKeySalt ) - const uint8_t *masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); + trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", MP_N, MP_r, MP_p ); + MPMasterKey masterKey = mpw_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); mpw_free( masterKeySalt, masterKeySaltSize ); if (!masterKey) { err( "Could not allocate master key: %s\n", strerror( errno ) ); return NULL; } - trc( "masterKey ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); + trc( " => masterKey.id: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); return masterKey; } @@ -65,81 +76,22 @@ static MPSiteKey mpw_siteKey_v3( MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, const MPKeyPurpose keyPurpose, const char *keyContext) { - const char *keyScope = mpw_scopeForPurpose( keyPurpose ); - trc( "-- mpw_siteKey_v3\n" ); - trc( "siteName: %s\n", siteName ); - trc( "siteCounter: %d\n", siteCounter ); - trc( "keyPurpose: %d\n", keyPurpose ); - trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "": keyContext ); - trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", - keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, - mpw_hex_l( htonl( siteCounter ) ), - mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext ); - - // Calculate the site seed. - // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . 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_string( &siteSalt, &siteSaltSize, siteName ); - mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) ); - if (keyContext) { - mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( keyContext ) ) ); - mpw_push_string( &siteSalt, &siteSaltSize, keyContext ); - } - if (!siteSalt) { - err( "Could not allocate site salt: %s\n", strerror( errno ) ); - return NULL; - } - trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) ); - - MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); - mpw_free( siteSalt, siteSaltSize ); - if (!siteKey || !siteSaltSize) { - err( "Could not allocate site key: %s\n", strerror( errno ) ); - mpw_free( siteSalt, siteSaltSize ); - return NULL; - } - trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); - - return siteKey; + return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext ); } static const char *mpw_sitePassword_v3( MPSiteKey siteKey, const MPPasswordType passwordType) { - trc( "-- mpw_sitePassword_v3\n" ); - trc( "passwordType: %d\n", passwordType ); - - // Determine the template. - const char *template = mpw_templateForType( passwordType, siteKey[0] ); - trc( "type %d, template: %s\n", passwordType, template ); - if (!template) - return NULL; - if (strlen( template ) > MPSiteKeySize) { - err( "Template too long for password seed: %lu\n", strlen( template ) ); - return NULL; - } - - // 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] ); - trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], siteKey[c + 1], siteKey[c + 1], - sitePassword[c] ); - } - - return sitePassword; + return mpw_sitePassword_v2( siteKey, passwordType ); } -const char *mpw_encrypt_v3( +static const char *mpw_encrypt_v3( MPMasterKey masterKey, const char *plainText) { return mpw_encrypt_v2( masterKey, plainText ); } -const char *mpw_decrypt_v3( +static const char *mpw_decrypt_v3( MPMasterKey masterKey, const char *cipherText) { return mpw_decrypt_v2( masterKey, cipherText ); diff --git a/core/c/mpw-util.c b/core/c/mpw-util.c index b0b8f184..f014f38c 100644 --- a/core/c/mpw-util.c +++ b/core/c/mpw-util.c @@ -383,7 +383,6 @@ static int mpw_utf8_sizeof(unsigned char utf8Byte) { const size_t mpw_utf8_strlen(const char *utf8String) { - // TODO: is this ever different from strlen? If not, remove. size_t charlen = 0; char *remainingString = (char *)utf8String; for (int charByteSize; (charByteSize = mpw_utf8_sizeof( (unsigned char)*remainingString )); remainingString += charByteSize)