2
0

Rename identifiers to align better with their meaning (siteVariant -> keyPurpose, siteContext -> keyContext, siteType -> passwordType).

This commit is contained in:
Maarten Billemont 2017-08-01 13:45:54 -04:00
parent 3c5cb1673a
commit 9d5105a9e5
16 changed files with 351 additions and 350 deletions

View File

@ -44,20 +44,20 @@ MPMasterKey mpw_masterKey(const char *fullName, const char *masterPassword, cons
MPSiteKey mpw_siteKey( MPSiteKey mpw_siteKey(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion) { const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) {
if (!masterKey || !siteName) if (!masterKey || !siteName)
return NULL; return NULL;
switch (algorithmVersion) { switch (algorithmVersion) {
case MPAlgorithmVersion0: case MPAlgorithmVersion0:
return mpw_siteKey_v0( masterKey, siteName, siteCounter, siteVariant, siteContext ); return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
case MPAlgorithmVersion1: case MPAlgorithmVersion1:
return mpw_siteKey_v1( masterKey, siteName, siteCounter, siteVariant, siteContext ); return mpw_siteKey_v1( masterKey, siteName, siteCounter, keyPurpose, keyContext );
case MPAlgorithmVersion2: case MPAlgorithmVersion2:
return mpw_siteKey_v2( masterKey, siteName, siteCounter, siteVariant, siteContext ); return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );
case MPAlgorithmVersion3: case MPAlgorithmVersion3:
return mpw_siteKey_v3( masterKey, siteName, siteCounter, siteVariant, siteContext ); return mpw_siteKey_v3( masterKey, siteName, siteCounter, keyPurpose, keyContext );
default: default:
ftl( "Unsupported version: %d", algorithmVersion ); ftl( "Unsupported version: %d", algorithmVersion );
return NULL; return NULL;
@ -65,20 +65,20 @@ MPSiteKey mpw_siteKey(
} }
const char *mpw_sitePassword( const char *mpw_sitePassword(
MPSiteKey siteKey, const MPSiteType siteType, const MPAlgorithmVersion algorithmVersion) { MPSiteKey siteKey, const MPPasswordType passwordType, const MPAlgorithmVersion algorithmVersion) {
if (!siteKey) if (!siteKey)
return NULL; return NULL;
switch (algorithmVersion) { switch (algorithmVersion) {
case MPAlgorithmVersion0: case MPAlgorithmVersion0:
return mpw_sitePassword_v0( siteKey, siteType ); return mpw_sitePassword_v0( siteKey, passwordType );
case MPAlgorithmVersion1: case MPAlgorithmVersion1:
return mpw_sitePassword_v1( siteKey, siteType ); return mpw_sitePassword_v1( siteKey, passwordType );
case MPAlgorithmVersion2: case MPAlgorithmVersion2:
return mpw_sitePassword_v2( siteKey, siteType ); return mpw_sitePassword_v2( siteKey, passwordType );
case MPAlgorithmVersion3: case MPAlgorithmVersion3:
return mpw_sitePassword_v3( siteKey, siteType ); return mpw_sitePassword_v3( siteKey, passwordType );
default: default:
ftl( "Unsupported version: %d", algorithmVersion ); ftl( "Unsupported version: %d", algorithmVersion );
return NULL; return NULL;

View File

@ -46,11 +46,11 @@ MPMasterKey mpw_masterKey(
* @return A new MPSiteKeySize-byte allocated buffer or NULL if an error occurred. */ * @return A new MPSiteKeySize-byte allocated buffer or NULL if an error occurred. */
MPSiteKey mpw_siteKey( MPSiteKey mpw_siteKey(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion); const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion);
/** Encode a password for the site from the given site key. /** Encode a password for the site from the given site key.
* @return A newly allocated string or NULL if an error occurred. */ * @return A newly allocated string or NULL if an error occurred. */
const char *mpw_sitePassword( const char *mpw_sitePassword(
MPSiteKey siteKey, const MPSiteType siteType, const MPAlgorithmVersion algorithmVersion); MPSiteKey siteKey, const MPPasswordType passwordType, const MPAlgorithmVersion algorithmVersion);
#endif // _MPW_ALGORITHM_H #endif // _MPW_ALGORITHM_H

View File

@ -28,7 +28,7 @@
#define MP_p 2 #define MP_p 2
#define MP_hash PearlHashSHA256 #define MP_hash PearlHashSHA256
static const char *mpw_templateForType_v0(MPSiteType type, uint16_t seedByte) { static const char *mpw_templateForType_v0(MPPasswordType type, uint16_t seedByte) {
size_t count = 0; size_t count = 0;
const char **templates = mpw_templatesForType( type, &count ); const char **templates = mpw_templatesForType( type, &count );
@ -45,7 +45,7 @@ static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedBy
static MPMasterKey mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) { static MPMasterKey mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword ); const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication );
trc( "algorithm: v%d\n", 0 ); trc( "algorithm: v%d\n", 0 );
trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) ); trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) );
trc( "masterPassword: %s\n", masterPassword ); trc( "masterPassword: %s\n", masterPassword );
@ -79,59 +79,60 @@ static MPMasterKey mpw_masterKeyForUser_v0(const char *fullName, const char *mas
static MPSiteKey mpw_siteKey_v0( static MPSiteKey mpw_siteKey_v0(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
const MPSiteVariant siteVariant, const char *siteContext) { const MPKeyPurpose keyPurpose, const char *keyContext) {
const char *siteScope = mpw_scopeForVariant( siteVariant ); const char *keyScope = mpw_scopeForPurpose( keyPurpose );
trc( "-- mpw_siteKey_v0\n" ); trc( "-- mpw_siteKey_v0\n" );
trc( "siteName: %s\n", siteName ); trc( "siteName: %s\n", siteName );
trc( "siteCounter: %d\n", siteCounter ); trc( "siteCounter: %d\n", siteCounter );
trc( "siteVariant: %d\n", siteVariant ); trc( "keyPurpose: %d\n", keyPurpose );
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext ); trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "<empty>": keyContext );
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
mpw_hex_l( htonl( siteCounter ) ), mpw_hex_l( htonl( siteCounter ) ),
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext ); mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext );
// Calculate the site seed. // Calculate the site seed.
// siteKey = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext ) // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . keyContext )
size_t sitePasswordInfoSize = 0; size_t siteSaltSize = 0;
uint8_t *sitePasswordInfo = NULL; uint8_t *siteSalt = NULL;
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteScope ); mpw_push_string( &siteSalt, &siteSaltSize, keyScope );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_utf8_strlen( siteName ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( siteName ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteName ); mpw_push_string( &siteSalt, &siteSaltSize, siteName );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) );
if (siteContext) { if (keyContext) {
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_utf8_strlen( siteContext ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( keyContext ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteContext ); mpw_push_string( &siteSalt, &siteSaltSize, keyContext );
} }
if (!sitePasswordInfo) { if (!siteSalt || !siteSaltSize) {
ftl( "Could not allocate site seed info: %d\n", errno ); ftl( "Could not allocate site salt: %d\n", errno );
mpw_free( siteSalt, siteSaltSize );
return NULL; return NULL;
} }
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) ); trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) );
MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize ); MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
mpw_free( sitePasswordInfo, sitePasswordInfoSize ); mpw_free( siteSalt, siteSaltSize );
if (!siteKey) { if (!siteKey) {
ftl( "Could not allocate site seed: %d\n", errno ); ftl( "Could not allocate site key: %d\n", errno );
return NULL; return NULL;
} }
trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, 32 ) ); trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
return siteKey; return siteKey;
} }
static const char *mpw_sitePassword_v0( static const char *mpw_sitePassword_v0(
MPSiteKey siteKey, const MPSiteType siteType) { MPSiteKey siteKey, const MPPasswordType passwordType) {
trc( "-- mpw_sitePassword_v0\n" ); trc( "-- mpw_sitePassword_v0\n" );
trc( "siteType: %d\n", siteType ); trc( "passwordType: %d\n", passwordType );
// Determine the template. // Determine the template.
const char *_siteKey = (const char *)siteKey; const char *_siteKey = (const char *)siteKey;
const char *template = mpw_templateForType_v0( siteType, htons( _siteKey[0] ) ); const char *template = mpw_templateForType_v0( passwordType, htons( _siteKey[0] ) );
trc( "type %d, template: %s\n", siteType, template ); trc( "type %d, template: %s\n", passwordType, template );
if (strlen( template ) > 32) { if (strlen( template ) > MPSiteKeySize) {
ftl( "Template too long for password seed: %lu", strlen( template ) ); ftl( "Template too long for password seed: %lu", strlen( template ) );
mpw_free( _siteKey, sizeof( _siteKey ) ); mpw_free( _siteKey, sizeof( _siteKey ) );
return NULL; return NULL;

View File

@ -29,7 +29,7 @@
static MPMasterKey mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) { static MPMasterKey mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword ); const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication );
trc( "algorithm: v%d\n", 1 ); trc( "algorithm: v%d\n", 1 );
trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) ); trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) );
trc( "masterPassword: %s\n", masterPassword ); trc( "masterPassword: %s\n", masterPassword );
@ -63,58 +63,59 @@ static MPMasterKey mpw_masterKeyForUser_v1(const char *fullName, const char *mas
static MPSiteKey mpw_siteKey_v1( static MPSiteKey mpw_siteKey_v1(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
const MPSiteVariant siteVariant, const char *siteContext) { const MPKeyPurpose keyPurpose, const char *keyContext) {
const char *siteScope = mpw_scopeForVariant( siteVariant ); const char *keyScope = mpw_scopeForPurpose( keyPurpose );
trc( "-- mpw_siteKey_v1\n" ); trc( "-- mpw_siteKey_v1\n" );
trc( "siteName: %s\n", siteName ); trc( "siteName: %s\n", siteName );
trc( "siteCounter: %d\n", siteCounter ); trc( "siteCounter: %d\n", siteCounter );
trc( "siteVariant: %d\n", siteVariant ); trc( "keyPurpose: %d\n", keyPurpose );
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext ); trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "<empty>": keyContext );
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
mpw_hex_l( htonl( siteCounter ) ), mpw_hex_l( htonl( siteCounter ) ),
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext ); mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext );
// Calculate the site seed. // Calculate the site seed.
// siteKey = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext ) // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . keyContext )
size_t sitePasswordInfoSize = 0; size_t siteSaltSize = 0;
uint8_t *sitePasswordInfo = NULL; uint8_t *siteSalt = NULL;
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteScope ); mpw_push_string( &siteSalt, &siteSaltSize, keyScope );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_utf8_strlen( siteName ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( siteName ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteName ); mpw_push_string( &siteSalt, &siteSaltSize, siteName );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) );
if (siteContext) { if (keyContext) {
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_utf8_strlen( siteContext ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( mpw_utf8_strlen( keyContext ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteContext ); mpw_push_string( &siteSalt, &siteSaltSize, keyContext );
} }
if (!sitePasswordInfo) { if (!siteSalt || !siteSaltSize) {
ftl( "Could not allocate site seed info: %d\n", errno ); ftl( "Could not allocate site salt: %d\n", errno );
mpw_free( siteSalt, siteSaltSize );
return NULL; return NULL;
} }
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) ); trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) );
MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize ); MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
mpw_free( sitePasswordInfo, sitePasswordInfoSize ); mpw_free( siteSalt, siteSaltSize );
if (!siteKey) { if (!siteKey) {
ftl( "Could not allocate site seed: %d\n", errno ); ftl( "Could not allocate site key: %d\n", errno );
return NULL; return NULL;
} }
trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, 32 ) ); trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
return siteKey; return siteKey;
} }
static const char *mpw_sitePassword_v1( static const char *mpw_sitePassword_v1(
MPSiteKey siteKey, const MPSiteType siteType) { MPSiteKey siteKey, const MPPasswordType passwordType) {
trc( "-- mpw_sitePassword_v1\n" ); trc( "-- mpw_sitePassword_v1\n" );
trc( "siteType: %d\n", siteType ); trc( "passwordType: %d\n", passwordType );
// Determine the template. // Determine the template.
const char *template = mpw_templateForType( siteType, siteKey[0] ); const char *template = mpw_templateForType( passwordType, siteKey[0] );
trc( "type %d, template: %s\n", siteType, template ); trc( "type %d, template: %s\n", passwordType, template );
if (strlen( template ) > 32) { if (strlen( template ) > MPSiteKeySize) {
ftl( "Template too long for password seed: %lu", strlen( template ) ); ftl( "Template too long for password seed: %lu", strlen( template ) );
mpw_free( siteKey, sizeof( siteKey ) ); mpw_free( siteKey, sizeof( siteKey ) );
return NULL; return NULL;

View File

@ -29,7 +29,7 @@
static MPMasterKey mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) { static MPMasterKey mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword ); const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication );
trc( "algorithm: v%d\n", 2 ); trc( "algorithm: v%d\n", 2 );
trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) ); trc( "fullName: %s (%zu)\n", fullName, mpw_utf8_strlen( fullName ) );
trc( "masterPassword: %s\n", masterPassword ); trc( "masterPassword: %s\n", masterPassword );
@ -63,58 +63,59 @@ static MPMasterKey mpw_masterKeyForUser_v2(const char *fullName, const char *mas
static MPSiteKey mpw_siteKey_v2( static MPSiteKey mpw_siteKey_v2(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
const MPSiteVariant siteVariant, const char *siteContext) { const MPKeyPurpose keyPurpose, const char *keyContext) {
const char *siteScope = mpw_scopeForVariant( siteVariant ); const char *keyScope = mpw_scopeForPurpose( keyPurpose );
trc( "-- mpw_siteKey_v2\n" ); trc( "-- mpw_siteKey_v2\n" );
trc( "siteName: %s\n", siteName ); trc( "siteName: %s\n", siteName );
trc( "siteCounter: %d\n", siteCounter ); trc( "siteCounter: %d\n", siteCounter );
trc( "siteVariant: %d\n", siteVariant ); trc( "keyPurpose: %d\n", keyPurpose );
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext ); trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "<empty>": keyContext );
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
mpw_hex_l( htonl( siteCounter ) ), mpw_hex_l( htonl( siteCounter ) ),
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext ); mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext );
// Calculate the site seed. // Calculate the site seed.
// siteKey = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext ) // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . keyContext )
size_t sitePasswordInfoSize = 0; size_t siteSaltSize = 0;
uint8_t *sitePasswordInfo = NULL; uint8_t *siteSalt = NULL;
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteScope ); mpw_push_string( &siteSalt, &siteSaltSize, keyScope );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( siteName ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteName ); mpw_push_string( &siteSalt, &siteSaltSize, siteName );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) );
if (siteContext) { if (keyContext) {
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( keyContext ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteContext ); mpw_push_string( &siteSalt, &siteSaltSize, keyContext );
} }
if (!sitePasswordInfo) { if (!siteSalt || !siteSaltSize) {
ftl( "Could not allocate site seed info: %d\n", errno ); ftl( "Could not allocate site salt: %d\n", errno );
mpw_free( siteSalt, siteSaltSize );
return NULL; return NULL;
} }
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) ); trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) );
const uint8_t *siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize ); const uint8_t *siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
mpw_free( sitePasswordInfo, sitePasswordInfoSize ); mpw_free( siteSalt, siteSaltSize );
if (!siteKey) { if (!siteKey) {
ftl( "Could not allocate site seed: %d\n", errno ); ftl( "Could not allocate site key: %d\n", errno );
return NULL; return NULL;
} }
trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, 32 ) ); trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
return siteKey; return siteKey;
} }
static const char *mpw_sitePassword_v2( static const char *mpw_sitePassword_v2(
MPSiteKey siteKey, const MPSiteType siteType) { MPSiteKey siteKey, const MPPasswordType passwordType) {
trc( "-- mpw_sitePassword_v2\n" ); trc( "-- mpw_sitePassword_v2\n" );
trc( "siteType: %d\n", siteType ); trc( "passwordType: %d\n", passwordType );
// Determine the template. // Determine the template.
const char *template = mpw_templateForType( siteType, siteKey[0] ); const char *template = mpw_templateForType( passwordType, siteKey[0] );
trc( "type %d, template: %s\n", siteType, template ); trc( "type %d, template: %s\n", passwordType, template );
if (strlen( template ) > 32) { if (strlen( template ) > MPSiteKeySize) {
ftl( "Template too long for password seed: %lu", strlen( template ) ); ftl( "Template too long for password seed: %lu", strlen( template ) );
mpw_free( siteKey, sizeof( siteKey ) ); mpw_free( siteKey, sizeof( siteKey ) );
return NULL; return NULL;

View File

@ -29,7 +29,7 @@
static MPMasterKey mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) { static MPMasterKey mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword ); const char *mpKeyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication );
trc( "-- mpw_masterKeyForUser_v3\n" ); trc( "-- mpw_masterKeyForUser_v3\n" );
trc( "fullName: %s (%zu)\n", fullName, strlen( fullName ) ); trc( "fullName: %s (%zu)\n", fullName, strlen( fullName ) );
trc( "masterPassword: %s\n", masterPassword ); trc( "masterPassword: %s\n", masterPassword );
@ -63,58 +63,59 @@ static MPMasterKey mpw_masterKeyForUser_v3(const char *fullName, const char *mas
static MPSiteKey mpw_siteKey_v3( static MPSiteKey mpw_siteKey_v3(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter, MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
const MPSiteVariant siteVariant, const char *siteContext) { const MPKeyPurpose keyPurpose, const char *keyContext) {
const char *siteScope = mpw_scopeForVariant( siteVariant ); const char *keyScope = mpw_scopeForPurpose( keyPurpose );
trc( "-- mpw_siteKey_v3\n" ); trc( "-- mpw_siteKey_v3\n" );
trc( "siteName: %s\n", siteName ); trc( "siteName: %s\n", siteName );
trc( "siteCounter: %d\n", siteCounter ); trc( "siteCounter: %d\n", siteCounter );
trc( "siteVariant: %d\n", siteVariant ); trc( "keyPurpose: %d\n", keyPurpose );
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext ); trc( "keyScope: %s, keyContext: %s\n", keyScope, keyContext? "<empty>": keyContext );
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", trc( "siteKey: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
mpw_hex_l( htonl( siteCounter ) ), mpw_hex_l( htonl( siteCounter ) ),
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext ); mpw_hex_l( htonl( keyContext? strlen( keyContext ): 0 ) ), keyContext? "(null)": keyContext );
// Calculate the site seed. // Calculate the site seed.
// siteKey = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext ) // siteKey = hmac-sha256( masterKey, keyScope . #siteName . siteName . siteCounter . #keyContext . keyContext )
size_t sitePasswordInfoSize = 0; size_t siteSaltSize = 0;
uint8_t *sitePasswordInfo = NULL; uint8_t *siteSalt = NULL;
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteScope ); mpw_push_string( &siteSalt, &siteSaltSize, keyScope );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( siteName ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteName ); mpw_push_string( &siteSalt, &siteSaltSize, siteName );
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( siteCounter ) );
if (siteContext) { if (keyContext) {
mpw_push_int( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) ); mpw_push_int( &siteSalt, &siteSaltSize, htonl( strlen( keyContext ) ) );
mpw_push_string( &sitePasswordInfo, &sitePasswordInfoSize, siteContext ); mpw_push_string( &siteSalt, &siteSaltSize, keyContext );
} }
if (!sitePasswordInfo) { if (!siteSalt) {
ftl( "Could not allocate site seed info: %d\n", errno ); ftl( "Could not allocate site salt: %d\n", errno );
return NULL; return NULL;
} }
trc( "sitePasswordInfo ID: %s\n", mpw_id_buf( sitePasswordInfo, sitePasswordInfoSize ) ); trc( "siteSalt ID: %s\n", mpw_id_buf( siteSalt, siteSaltSize ) );
MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, sitePasswordInfoSize ); MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
mpw_free( sitePasswordInfo, sitePasswordInfoSize ); mpw_free( siteSalt, siteSaltSize );
if (!siteKey) { if (!siteKey || !siteSaltSize) {
ftl( "Could not allocate site seed: %d\n", errno ); ftl( "Could not allocate site key: %d\n", errno );
mpw_free( siteSalt, siteSaltSize );
return NULL; return NULL;
} }
trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, 32 ) ); trc( "siteKey ID: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
return siteKey; return siteKey;
} }
static const char *mpw_sitePassword_v3( static const char *mpw_sitePassword_v3(
MPSiteKey siteKey, const MPSiteType siteType) { MPSiteKey siteKey, const MPPasswordType passwordType) {
trc( "-- mpw_sitePassword_v3\n" ); trc( "-- mpw_sitePassword_v3\n" );
trc( "siteType: %d\n", siteType ); trc( "passwordType: %d\n", passwordType );
// Determine the template. // Determine the template.
const char *template = mpw_templateForType( siteType, siteKey[0] ); const char *template = mpw_templateForType( passwordType, siteKey[0] );
trc( "type %d, template: %s\n", siteType, template ); trc( "type %d, template: %s\n", passwordType, template );
if (strlen( template ) > 32) { if (strlen( template ) > MPSiteKeySize) {
ftl( "Template too long for password seed: %lu", strlen( template ) ); ftl( "Template too long for password seed: %lu", strlen( template ) );
mpw_free( siteKey, sizeof( siteKey ) ); mpw_free( siteKey, sizeof( siteKey ) );
return NULL; return NULL;

View File

@ -38,7 +38,7 @@ MPMarshalledUser *mpw_marshall_user(
.redacted = true, .redacted = true,
.avatar = 0, .avatar = 0,
.defaultType = MPSiteTypeDefault, .defaultType = MPPasswordTypeDefault,
.lastUsed = 0, .lastUsed = 0,
.sites_count = 0, .sites_count = 0,
@ -49,7 +49,7 @@ MPMarshalledUser *mpw_marshall_user(
MPMarshalledSite *mpw_marshall_site( MPMarshalledSite *mpw_marshall_site(
MPMarshalledUser *marshalledUser, MPMarshalledUser *marshalledUser,
const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion) { const char *siteName, const MPPasswordType siteType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion) {
if (!siteName || !(marshalledUser->sites = if (!siteName || !(marshalledUser->sites =
realloc( marshalledUser->sites, sizeof( MPMarshalledSite ) * (++marshalledUser->sites_count) ))) realloc( marshalledUser->sites, sizeof( MPMarshalledSite ) * (++marshalledUser->sites_count) )))
@ -170,8 +170,8 @@ static bool mpw_marshall_write_flat(
return false; return false;
} }
if (site.type & MPSiteTypeClassGenerated) { if (site.type & MPPasswordTypeClassGenerated) {
MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, site.counter, MPSiteVariantPassword, NULL, site.algorithm ); MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, site.counter, MPKeyPurposeAuthentication, NULL, site.algorithm );
content = mpw_sitePassword( siteKey, site.type, site.algorithm ); content = mpw_sitePassword( siteKey, site.type, site.algorithm );
mpw_free( siteKey, MPSiteKeySize ); mpw_free( siteKey, MPSiteKeySize );
} }
@ -253,8 +253,8 @@ static bool mpw_marshall_write_json(
return false; return false;
} }
if (site.type & MPSiteTypeClassGenerated) { if (site.type & MPPasswordTypeClassGenerated) {
MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, site.counter, MPSiteVariantPassword, NULL, site.algorithm ); MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, site.counter, MPKeyPurposeAuthentication, NULL, site.algorithm );
content = mpw_sitePassword( siteKey, site.type, site.algorithm ); content = mpw_sitePassword( siteKey, site.type, site.algorithm );
mpw_free( siteKey, MPSiteKeySize ); mpw_free( siteKey, MPSiteKeySize );
} }
@ -290,8 +290,8 @@ static bool mpw_marshall_write_json(
json_object_object_add( json_site_questions, question.keyword, json_site_question ); json_object_object_add( json_site_questions, question.keyword, json_site_question );
if (!user->redacted) { if (!user->redacted) {
MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, 1, MPSiteVariantAnswer, question.keyword, site.algorithm ); MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, 1, MPKeyPurposeRecovery, question.keyword, site.algorithm );
const char *answer = mpw_sitePassword( siteKey, MPSiteTypeGeneratedPhrase, site.algorithm ); const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site.algorithm );
mpw_free( siteKey, MPSiteKeySize ); mpw_free( siteKey, MPSiteKeySize );
if (answer) if (answer)
json_object_object_add( json_site_question, "answer", json_object_new_string( answer ) ); json_object_object_add( json_site_question, "answer", json_object_new_string( answer ) );
@ -338,7 +338,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
unsigned int importFormat = 0, importAvatar = 0; unsigned int importFormat = 0, importAvatar = 0;
char *importUserName = NULL, *importKeyID = NULL, *importDate = NULL; char *importUserName = NULL, *importKeyID = NULL, *importDate = NULL;
MPAlgorithmVersion importAlgorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1; MPAlgorithmVersion importAlgorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1;
MPSiteType importDefaultType = MPSiteTypeDefault; MPPasswordType importDefaultType = MPPasswordTypeDefault;
bool headerStarted = false, headerEnded = false, importRedacted = false; bool headerStarted = false, headerEnded = false, importRedacted = false;
for (char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) { for (char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) {
@ -391,7 +391,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
importAlgorithm = (MPAlgorithmVersion)importAlgorithmInt; importAlgorithm = (MPAlgorithmVersion)importAlgorithmInt;
} }
if (strcmp( headerName, "Default Type" ) == 0) if (strcmp( headerName, "Default Type" ) == 0)
importDefaultType = (MPSiteType)atoi( headerValue ); importDefaultType = (MPPasswordType)atoi( headerValue );
if (strcmp( headerName, "Passwords" ) == 0) if (strcmp( headerName, "Passwords" ) == 0)
importRedacted = strcmp( headerValue, "VISIBLE" ) != 0; importRedacted = strcmp( headerValue, "VISIBLE" ) != 0;
@ -479,7 +479,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
} }
MPMarshalledSite *site = mpw_marshall_site( user, siteName, MPMarshalledSite *site = mpw_marshall_site( user, siteName,
(MPSiteType)atoi( siteType ), (uint32_t)atoi( siteCounter ), siteAlgorithmInt ); (MPPasswordType)atoi( siteType ), (uint32_t)atoi( siteCounter ), siteAlgorithmInt );
if (!site) { if (!site) {
err( "Couldn't allocate a new site.\n" ); err( "Couldn't allocate a new site.\n" );
return NULL; return NULL;
@ -565,7 +565,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
*error = MPMarshallErrorIllegal; *error = MPMarshallErrorIllegal;
return NULL; return NULL;
} }
MPSiteType defaultType = (MPSiteType)mpw_get_json_int( json_file, "user.default_type", MPSiteTypeDefault ); MPPasswordType defaultType = (MPPasswordType)mpw_get_json_int( json_file, "user.default_type", MPPasswordTypeDefault );
if (!fullName || !strlen( fullName )) { if (!fullName || !strlen( fullName )) {
err( "Missing value for full name.\n" ); err( "Missing value for full name.\n" );
@ -595,7 +595,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
json_object_iter json_site; json_object_iter json_site;
json_object *json_sites = mpw_get_json_section( json_file, "sites" ); json_object *json_sites = mpw_get_json_section( json_file, "sites" );
json_object_object_foreachC( json_sites, json_site ) { json_object_object_foreachC( json_sites, json_site ) {
MPSiteType siteType = (MPSiteType)mpw_get_json_int( json_site.val, "type", (int)user->defaultType ); MPPasswordType siteType = (MPPasswordType)mpw_get_json_int( json_site.val, "type", (int)user->defaultType );
uint32_t siteCounter = (uint32_t)mpw_get_json_int( json_site.val, "counter", 1 ); uint32_t siteCounter = (uint32_t)mpw_get_json_int( json_site.val, "counter", 1 );
MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)mpw_get_json_int( json_site.val, "algorithm", (int)user->algorithm ); MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)mpw_get_json_int( json_site.val, "algorithm", (int)user->algorithm );
if (siteAlgorithm < MPAlgorithmVersionFirst || siteAlgorithm > MPAlgorithmVersionLast) { if (siteAlgorithm < MPAlgorithmVersionFirst || siteAlgorithm > MPAlgorithmVersionLast) {

View File

@ -56,7 +56,7 @@ typedef struct MPMarshalledQuestion {
typedef struct MPMarshalledSite { typedef struct MPMarshalledSite {
const char *name; const char *name;
const char *content; const char *content;
MPSiteType type; MPPasswordType type;
uint32_t counter; uint32_t counter;
MPAlgorithmVersion algorithm; MPAlgorithmVersion algorithm;
@ -78,7 +78,7 @@ typedef struct MPMarshalledUser {
bool redacted; bool redacted;
unsigned int avatar; unsigned int avatar;
MPSiteType defaultType; MPPasswordType defaultType;
time_t lastUsed; time_t lastUsed;
size_t sites_count; size_t sites_count;
@ -101,7 +101,7 @@ MPMarshalledUser *mpw_marshall_user(
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion); const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
MPMarshalledSite *mpw_marshall_site( MPMarshalledSite *mpw_marshall_site(
MPMarshalledUser *marshalledUser, MPMarshalledUser *marshalledUser,
const char *siteName, const MPSiteType siteType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion); const char *siteName, const MPPasswordType siteType, const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion);
MPMarshalledQuestion *mpw_marshal_question( MPMarshalledQuestion *mpw_marshal_question(
MPMarshalledSite *marshalledSite, const char *keyword); MPMarshalledSite *marshalledSite, const char *keyword);
bool mpw_marshal_free( bool mpw_marshal_free(

View File

@ -29,54 +29,53 @@
#include "mpw-types.h" #include "mpw-types.h"
#include "mpw-util.h" #include "mpw-util.h"
const MPSiteType mpw_typeWithName(const char *typeName) { const MPPasswordType mpw_typeWithName(const char *typeName) {
// Lower-case and trim optionally leading "Generated" string from typeName to standardize it. // Lower-case and trim optionally leading "Generated" string from typeName to standardize it.
size_t stdTypeNameOffset = 0; size_t stdTypeNameOffset = 0;
size_t stdTypeNameSize = strlen( typeName ); size_t stdTypeNameSize = strlen( typeName );
if (strstr(typeName, "Generated" ) == typeName) if (strstr( typeName, "Generated" ) == typeName)
stdTypeNameSize -= (stdTypeNameOffset = strlen( "Generated" )); stdTypeNameSize -= (stdTypeNameOffset = strlen( "Generated" ));
char stdTypeName[stdTypeNameSize + 1]; char stdTypeName[stdTypeNameSize + 1];
for (size_t c = 0; c < stdTypeNameSize; ++c) for (size_t c = 0; c < stdTypeNameSize; ++c)
stdTypeName[c] = (char)tolower( typeName[c + stdTypeNameOffset] ); stdTypeName[c] = (char)tolower( typeName[c + stdTypeNameOffset] );
stdTypeName[stdTypeNameSize] = '\0'; stdTypeName[stdTypeNameSize] = '\0';
// Find what site type is represented by the type name. // Find what password type is represented by the type name.
if (0 == strcmp( stdTypeName, "x" ) || 0 == strcmp( stdTypeName, "max" ) || 0 == strcmp( stdTypeName, "maximum" )) if (0 == strncmp( "maximum", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "x", stdTypeName, 1 ))
return MPSiteTypeGeneratedMaximum; return MPPasswordTypeGeneratedMaximum;
if (0 == strcmp( stdTypeName, "l" ) || 0 == strcmp( stdTypeName, "long" )) if (0 == strncmp( "long", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "l", stdTypeName, 1 ))
return MPSiteTypeGeneratedLong; return MPPasswordTypeGeneratedLong;
if (0 == strcmp( stdTypeName, "m" ) || 0 == strcmp( stdTypeName, "med" ) || 0 == strcmp( stdTypeName, "medium" )) if (0 == strncmp( "medium", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "m", stdTypeName, 1 ))
return MPSiteTypeGeneratedMedium; return MPPasswordTypeGeneratedMedium;
if (0 == strcmp( stdTypeName, "b" ) || 0 == strcmp( stdTypeName, "basic" )) if (0 == strncmp( "basic", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "b", stdTypeName, 1 ))
return MPSiteTypeGeneratedBasic; return MPPasswordTypeGeneratedBasic;
if (0 == strcmp( stdTypeName, "s" ) || 0 == strcmp( stdTypeName, "short" )) if (0 == strncmp( "short", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "s", stdTypeName, 1 ))
return MPSiteTypeGeneratedShort; return MPPasswordTypeGeneratedShort;
if (0 == strcmp( stdTypeName, "i" ) || 0 == strcmp( stdTypeName, "pin" )) if (0 == strncmp( "pin", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "i", stdTypeName, 1 ))
return MPSiteTypeGeneratedPIN; return MPPasswordTypeGeneratedPIN;
if (0 == strcmp( stdTypeName, "n" ) || 0 == strcmp( stdTypeName, "name" )) if (0 == strncmp( "name", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "n", stdTypeName, 1 ))
return MPSiteTypeGeneratedName; return MPPasswordTypeGeneratedName;
if (0 == strcmp( stdTypeName, "p" ) || 0 == strcmp( stdTypeName, "phrase" )) if (0 == strncmp( "phrase", stdTypeName, strlen( stdTypeName ) ) || 0 == strncmp( "p", stdTypeName, 1 ))
return MPSiteTypeGeneratedPhrase; return MPPasswordTypeGeneratedPhrase;
ftl( "Not a generated type name: %s", stdTypeName ); ftl( "Not a generated type name: %s", stdTypeName );
return MPSiteTypeDefault; return MPPasswordTypeDefault;
} }
const char **mpw_templatesForType(MPSiteType type, size_t *count) { const char **mpw_templatesForType(MPPasswordType type, size_t *count) {
if (!(type & MPSiteTypeClassGenerated)) { if (!(type & MPPasswordTypeClassGenerated)) {
ftl( "Not a generated type: %d", type ); ftl( "Not a generated type: %d", type );
*count = 0; *count = 0;
return NULL; return NULL;
} }
switch (type) { switch (type) {
case MPSiteTypeGeneratedMaximum: { case MPPasswordTypeGeneratedMaximum:
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" ); "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" );
} case MPPasswordTypeGeneratedLong:
case MPSiteTypeGeneratedLong: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
@ -85,31 +84,24 @@ const char **mpw_templatesForType(MPSiteType type, size_t *count) {
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" ); "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" );
} case MPPasswordTypeGeneratedMedium:
case MPSiteTypeGeneratedMedium: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"CvcnoCvc", "CvcCvcno" ); "CvcnoCvc", "CvcCvcno" );
} case MPPasswordTypeGeneratedBasic:
case MPSiteTypeGeneratedBasic: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"aaanaaan", "aannaaan", "aaannaaa" ); "aaanaaan", "aannaaan", "aaannaaa" );
} case MPPasswordTypeGeneratedShort:
case MPSiteTypeGeneratedShort: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"Cvcn" ); "Cvcn" );
} case MPPasswordTypeGeneratedPIN:
case MPSiteTypeGeneratedPIN: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"nnnn" ); "nnnn" );
} case MPPasswordTypeGeneratedName:
case MPSiteTypeGeneratedName: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"cvccvcvcv" ); "cvccvcvcv" );
} case MPPasswordTypeGeneratedPhrase:
case MPSiteTypeGeneratedPhrase: {
return mpw_alloc_array( *count, const char *, return mpw_alloc_array( *count, const char *,
"cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" ); "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" );
}
default: { default: {
ftl( "Unknown generated type: %d", type ); ftl( "Unknown generated type: %d", type );
*count = 0; *count = 0;
@ -118,7 +110,7 @@ const char **mpw_templatesForType(MPSiteType type, size_t *count) {
} }
} }
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) { const char *mpw_templateForType(MPPasswordType type, uint8_t seedByte) {
size_t count = 0; size_t count = 0;
const char **templates = mpw_templatesForType( type, &count ); const char **templates = mpw_templatesForType( type, &count );
@ -127,39 +119,37 @@ const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) {
return template; return template;
} }
const MPSiteVariant mpw_variantWithName(const char *variantName) { const MPKeyPurpose mpw_purposeWithName(const char *purposeName) {
// Lower-case and trim optionally leading "generated" string from typeName to standardize it. // Lower-case and trim optionally leading "generated" string from typeName to standardize it.
size_t stdVariantNameSize = strlen( variantName ); size_t stdPurposeNameSize = strlen( purposeName );
char stdVariantName[stdVariantNameSize + 1]; char stdPurposeName[stdPurposeNameSize + 1];
for (size_t c = 0; c < stdVariantNameSize; ++c) for (size_t c = 0; c < stdPurposeNameSize; ++c)
stdVariantName[c] = (char)tolower( variantName[c] ); stdPurposeName[c] = (char)tolower( purposeName[c] );
stdVariantName[stdVariantNameSize] = '\0'; stdPurposeName[stdPurposeNameSize] = '\0';
if (0 == strcmp( stdVariantName, "p" ) || 0 == strcmp( stdVariantName, "password" )) if (strncmp( "authentication", stdPurposeName, strlen( stdPurposeName ) ) == 0)
return MPSiteVariantPassword; return MPKeyPurposeAuthentication;
if (0 == strcmp( stdVariantName, "l" ) || 0 == strcmp( stdVariantName, "login" )) if (strncmp( "identification", stdPurposeName, strlen( stdPurposeName ) ) == 0)
return MPSiteVariantLogin; return MPKeyPurposeIdentification;
if (0 == strcmp( stdVariantName, "a" ) || 0 == strcmp( stdVariantName, "answer" )) if (strncmp( "recovery", stdPurposeName, strlen( stdPurposeName ) ) == 0)
return MPSiteVariantAnswer; return MPKeyPurposeRecovery;
ftl( "Not a variant name: %s", stdVariantName ); ftl( "Not a purpose name: %s", stdPurposeName );
} }
const char *mpw_scopeForVariant(MPSiteVariant variant) { const char *mpw_scopeForPurpose(MPKeyPurpose purpose) {
switch (variant) { switch (purpose) {
case MPSiteVariantPassword: { case MPKeyPurposeAuthentication:
return "com.lyndir.masterpassword"; return "com.lyndir.masterpassword";
} case MPKeyPurposeIdentification:
case MPSiteVariantLogin: {
return "com.lyndir.masterpassword.login"; return "com.lyndir.masterpassword.login";
} case MPKeyPurposeRecovery:
case MPSiteVariantAnswer: {
return "com.lyndir.masterpassword.answer"; return "com.lyndir.masterpassword.answer";
}
default: { default: {
ftl( "Unknown variant: %d", variant ); ftl( "Unknown purpose: %d", purpose );
return "";
} }
} }
} }
@ -189,6 +179,7 @@ const char *mpw_charactersInClass(char characterClass) {
return " "; return " ";
default: { default: {
ftl( "Unknown character class: %c", characterClass ); ftl( "Unknown character class: %c", characterClass );
return "";
} }
} }
} }

View File

@ -37,20 +37,20 @@ typedef const uint8_t *MPMasterKey;
typedef const uint8_t *MPSiteKey; typedef const uint8_t *MPSiteKey;
typedef const char *MPKeyID; typedef const char *MPKeyID;
typedef enum( unsigned int, MPSiteVariant ) { typedef enum( unsigned int, MPKeyPurpose ) {
/** Generate a key for authentication. */ /** Generate a key for authentication. */
MPSiteVariantPassword, MPKeyPurposeAuthentication,
/** Generate a name for identification. */ /** Generate a name for identification. */
MPSiteVariantLogin, MPKeyPurposeIdentification,
/** Generate an answer to a security question. */ /** Generate a recovery token. */
MPSiteVariantAnswer, MPKeyPurposeRecovery,
}; };
typedef enum( unsigned int, MPSiteTypeClass ) { typedef enum( unsigned int, MPPasswordTypeClass ) {
/** Generate the password. */ /** Generate the password. */
MPSiteTypeClassGenerated = 1 << 4, MPPasswordTypeClassGenerated = 1 << 4,
/** Store the password. */ /** Store the password. */
MPSiteTypeClassStored = 1 << 5, MPPasswordTypeClassStored = 1 << 5,
}; };
typedef enum( unsigned int, MPSiteFeature ) { typedef enum( unsigned int, MPSiteFeature ) {
@ -60,37 +60,47 @@ typedef enum( unsigned int, MPSiteFeature ) {
MPSiteFeatureDevicePrivate = 1 << 11, MPSiteFeatureDevicePrivate = 1 << 11,
}; };
typedef enum( unsigned int, MPSiteType ) { typedef enum( unsigned int, MPPasswordType ) {
MPSiteTypeGeneratedMaximum = 0x0 | MPSiteTypeClassGenerated | 0x0, /** pg^VMAUBk5x3p%HP%i4= */
MPSiteTypeGeneratedLong = 0x1 | MPSiteTypeClassGenerated | 0x0, MPPasswordTypeGeneratedMaximum = 0x0 | MPPasswordTypeClassGenerated | 0x0,
MPSiteTypeGeneratedMedium = 0x2 | MPSiteTypeClassGenerated | 0x0, /** BiroYena8:Kixa */
MPSiteTypeGeneratedBasic = 0x4 | MPSiteTypeClassGenerated | 0x0, MPPasswordTypeGeneratedLong = 0x1 | MPPasswordTypeClassGenerated | 0x0,
MPSiteTypeGeneratedShort = 0x3 | MPSiteTypeClassGenerated | 0x0, /** BirSuj0- */
MPSiteTypeGeneratedPIN = 0x5 | MPSiteTypeClassGenerated | 0x0, MPPasswordTypeGeneratedMedium = 0x2 | MPPasswordTypeClassGenerated | 0x0,
MPSiteTypeGeneratedName = 0xE | MPSiteTypeClassGenerated | 0x0, /** pO98MoD0 */
MPSiteTypeGeneratedPhrase = 0xF | MPSiteTypeClassGenerated | 0x0, MPPasswordTypeGeneratedBasic = 0x4 | MPPasswordTypeClassGenerated | 0x0,
/** Bir8 */
MPPasswordTypeGeneratedShort = 0x3 | MPPasswordTypeClassGenerated | 0x0,
/** 2798 */
MPPasswordTypeGeneratedPIN = 0x5 | MPPasswordTypeClassGenerated | 0x0,
/** birsujano */
MPPasswordTypeGeneratedName = 0xE | MPPasswordTypeClassGenerated | 0x0,
/** bir yennoquce fefi */
MPPasswordTypeGeneratedPhrase = 0xF | MPPasswordTypeClassGenerated | 0x0,
MPSiteTypeStoredPersonal = 0x0 | MPSiteTypeClassStored | MPSiteFeatureExportContent, /** Custom saved password. */
MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate, MPPasswordTypeStoredPersonal = 0x0 | MPPasswordTypeClassStored | MPSiteFeatureExportContent,
/** Custom saved password that should not be exported from the device. */
MPPasswordTypeStoredDevicePrivate = 0x1 | MPPasswordTypeClassStored | MPSiteFeatureDevicePrivate,
MPSiteTypeDefault = MPSiteTypeGeneratedLong, MPPasswordTypeDefault = MPPasswordTypeGeneratedLong,
}; };
//// Type utilities. //// Type utilities.
/** /**
* @return The variant represented by the given name. * @return The purpose represented by the given name.
*/ */
const MPSiteVariant mpw_variantWithName(const char *variantName); const MPKeyPurpose mpw_purposeWithName(const char *purposeName);
/** /**
* @return An internal string containing the scope identifier to apply when encoding for the given variant. * @return An internal string containing the scope identifier to apply when encoding for the given purpose.
*/ */
const char *mpw_scopeForVariant(MPSiteVariant variant); const char *mpw_scopeForPurpose(MPKeyPurpose purpose);
/** /**
* @return The type represented by the given name. * @return The type represented by the given name.
*/ */
const MPSiteType mpw_typeWithName(const char *typeName); const MPPasswordType mpw_typeWithName(const char *typeName);
/** /**
* @return A newly allocated array of internal strings that express the templates to use for the given type. * @return A newly allocated array of internal strings that express the templates to use for the given type.
@ -98,12 +108,12 @@ const MPSiteType mpw_typeWithName(const char *typeName);
* If an unsupported type is given, count will be 0 and will return NULL. * If an unsupported type is given, count will be 0 and will return NULL.
* The array needs to be free'ed, the strings themselves must not be free'ed or modified. * The array needs to be free'ed, the strings themselves must not be free'ed or modified.
*/ */
const char **mpw_templatesForType(MPSiteType type, size_t *count); const char **mpw_templatesForType(MPPasswordType type, size_t *count);
/** /**
* @return An internal string that contains the password encoding template of the given type * @return An internal string that contains the password encoding template of the given type
* for a seed that starts with the given byte. * for a seed that starts with the given byte.
*/ */
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte); const char *mpw_templateForType(MPPasswordType type, uint8_t seedByte);
/** /**
* @return An internal string that contains all the characters that occur in the given character class. * @return An internal string that contains all the characters that occur in the given character class.

View File

@ -288,6 +288,7 @@ static int mpw_utf8_sizeof(unsigned char utf8Byte) {
const size_t mpw_utf8_strlen(const char *utf8String) { const size_t mpw_utf8_strlen(const char *utf8String) {
// TODO: is this ever different from strlen?
size_t charlen = 0; size_t charlen = 0;
char *remainingString = (char *)utf8String; char *remainingString = (char *)utf8String;
for (int charByteSize; (charByteSize = mpw_utf8_sizeof( (unsigned char)*remainingString )); remainingString += charByteSize) for (int charByteSize; (charByteSize = mpw_utf8_sizeof( (unsigned char)*remainingString )); remainingString += charByteSize)

View File

@ -7,8 +7,8 @@
<keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID> <keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID>
<siteName>masterpasswordapp.com</siteName> <siteName>masterpasswordapp.com</siteName>
<siteCounter>1</siteCounter> <siteCounter>1</siteCounter>
<siteType>GeneratedLong</siteType> <passwordType>GeneratedLong</passwordType>
<siteVariant>Password</siteVariant> <keyPurpose>Password</keyPurpose>
<result><!-- abstract --></result> <result><!-- abstract --></result>
</case> </case>
@ -32,45 +32,45 @@
<result>LiheCuwhSerz6)</result> <result>LiheCuwhSerz6)</result>
</case> </case>
<case id="v3_loginName" parent="v3"> <case id="v3_loginName" parent="v3">
<siteVariant>Login</siteVariant> <keyPurpose>Login</keyPurpose>
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>wohzaqage</result> <result>wohzaqage</result>
</case> </case>
<case id="v3_securityAnswer" parent="v3"> <case id="v3_securityAnswer" parent="v3">
<siteVariant>Answer</siteVariant> <keyPurpose>Answer</keyPurpose>
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>xin diyjiqoja hubu</result> <result>xin diyjiqoja hubu</result>
</case> </case>
<case id="v3_securityAnswer_context" parent="v3_securityAnswer"> <case id="v3_securityAnswer_context" parent="v3_securityAnswer">
<siteContext>question</siteContext> <keyContext>question</keyContext>
<result>xogx tem cegyiva jab</result> <result>xogx tem cegyiva jab</result>
</case> </case>
<case id="v3_type_maximum" parent="v3"> <case id="v3_type_maximum" parent="v3">
<siteType>GeneratedMaximum</siteType> <passwordType>GeneratedMaximum</passwordType>
<result>W6@692^B1#&amp;@gVdSdLZ@</result> <result>W6@692^B1#&amp;@gVdSdLZ@</result>
</case> </case>
<case id="v3_type_medium" parent="v3"> <case id="v3_type_medium" parent="v3">
<siteType>GeneratedMedium</siteType> <passwordType>GeneratedMedium</passwordType>
<result>Jej2$Quv</result> <result>Jej2$Quv</result>
</case> </case>
<case id="v3_type_basic" parent="v3"> <case id="v3_type_basic" parent="v3">
<siteType>GeneratedBasic</siteType> <passwordType>GeneratedBasic</passwordType>
<result>WAo2xIg6</result> <result>WAo2xIg6</result>
</case> </case>
<case id="v3_type_short" parent="v3"> <case id="v3_type_short" parent="v3">
<siteType>GeneratedShort</siteType> <passwordType>GeneratedShort</passwordType>
<result>Jej2</result> <result>Jej2</result>
</case> </case>
<case id="v3_type_pin" parent="v3"> <case id="v3_type_pin" parent="v3">
<siteType>GeneratedPIN</siteType> <passwordType>GeneratedPIN</passwordType>
<result>7662</result> <result>7662</result>
</case> </case>
<case id="v3_type_name" parent="v3"> <case id="v3_type_name" parent="v3">
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>jejraquvo</result> <result>jejraquvo</result>
</case> </case>
<case id="v3_type_phrase" parent="v3"> <case id="v3_type_phrase" parent="v3">
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>jejr quv cabsibu tam</result> <result>jejr quv cabsibu tam</result>
</case> </case>
<case id="v3_counter_ceiling" parent="v3"> <case id="v3_counter_ceiling" parent="v3">
@ -98,45 +98,45 @@
<result>LiheCuwhSerz6)</result> <result>LiheCuwhSerz6)</result>
</case> </case>
<case id="v2_loginName" parent="v2"> <case id="v2_loginName" parent="v2">
<siteVariant>Login</siteVariant> <keyPurpose>Login</keyPurpose>
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>wohzaqage</result> <result>wohzaqage</result>
</case> </case>
<case id="v2_securityAnswer" parent="v2"> <case id="v2_securityAnswer" parent="v2">
<siteVariant>Answer</siteVariant> <keyPurpose>Answer</keyPurpose>
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>xin diyjiqoja hubu</result> <result>xin diyjiqoja hubu</result>
</case> </case>
<case id="v2_securityAnswer_context" parent="v2_securityAnswer"> <case id="v2_securityAnswer_context" parent="v2_securityAnswer">
<siteContext>question</siteContext> <keyContext>question</keyContext>
<result>xogx tem cegyiva jab</result> <result>xogx tem cegyiva jab</result>
</case> </case>
<case id="v2_type_maximum" parent="v2"> <case id="v2_type_maximum" parent="v2">
<siteType>GeneratedMaximum</siteType> <passwordType>GeneratedMaximum</passwordType>
<result>W6@692^B1#&amp;@gVdSdLZ@</result> <result>W6@692^B1#&amp;@gVdSdLZ@</result>
</case> </case>
<case id="v2_type_medium" parent="v2"> <case id="v2_type_medium" parent="v2">
<siteType>GeneratedMedium</siteType> <passwordType>GeneratedMedium</passwordType>
<result>Jej2$Quv</result> <result>Jej2$Quv</result>
</case> </case>
<case id="v2_type_basic" parent="v2"> <case id="v2_type_basic" parent="v2">
<siteType>GeneratedBasic</siteType> <passwordType>GeneratedBasic</passwordType>
<result>WAo2xIg6</result> <result>WAo2xIg6</result>
</case> </case>
<case id="v2_type_short" parent="v2"> <case id="v2_type_short" parent="v2">
<siteType>GeneratedShort</siteType> <passwordType>GeneratedShort</passwordType>
<result>Jej2</result> <result>Jej2</result>
</case> </case>
<case id="v2_type_pin" parent="v2"> <case id="v2_type_pin" parent="v2">
<siteType>GeneratedPIN</siteType> <passwordType>GeneratedPIN</passwordType>
<result>7662</result> <result>7662</result>
</case> </case>
<case id="v2_type_name" parent="v2"> <case id="v2_type_name" parent="v2">
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>jejraquvo</result> <result>jejraquvo</result>
</case> </case>
<case id="v2_type_phrase" parent="v2"> <case id="v2_type_phrase" parent="v2">
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>jejr quv cabsibu tam</result> <result>jejr quv cabsibu tam</result>
</case> </case>
<case id="v2_counter_ceiling" parent="v2"> <case id="v2_counter_ceiling" parent="v2">
@ -164,45 +164,45 @@
<result>WawiYarp2@Kodh</result> <result>WawiYarp2@Kodh</result>
</case> </case>
<case id="v1_loginName" parent="v1"> <case id="v1_loginName" parent="v1">
<siteVariant>Login</siteVariant> <keyPurpose>Login</keyPurpose>
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>wohzaqage</result> <result>wohzaqage</result>
</case> </case>
<case id="v1_securityAnswer" parent="v1"> <case id="v1_securityAnswer" parent="v1">
<siteVariant>Answer</siteVariant> <keyPurpose>Answer</keyPurpose>
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>xin diyjiqoja hubu</result> <result>xin diyjiqoja hubu</result>
</case> </case>
<case id="v1_securityAnswer_context" parent="v1_securityAnswer"> <case id="v1_securityAnswer_context" parent="v1_securityAnswer">
<siteContext>question</siteContext> <keyContext>question</keyContext>
<result>xogx tem cegyiva jab</result> <result>xogx tem cegyiva jab</result>
</case> </case>
<case id="v1_type_maximum" parent="v1"> <case id="v1_type_maximum" parent="v1">
<siteType>GeneratedMaximum</siteType> <passwordType>GeneratedMaximum</passwordType>
<result>W6@692^B1#&amp;@gVdSdLZ@</result> <result>W6@692^B1#&amp;@gVdSdLZ@</result>
</case> </case>
<case id="v1_type_medium" parent="v1"> <case id="v1_type_medium" parent="v1">
<siteType>GeneratedMedium</siteType> <passwordType>GeneratedMedium</passwordType>
<result>Jej2$Quv</result> <result>Jej2$Quv</result>
</case> </case>
<case id="v1_type_basic" parent="v1"> <case id="v1_type_basic" parent="v1">
<siteType>GeneratedBasic</siteType> <passwordType>GeneratedBasic</passwordType>
<result>WAo2xIg6</result> <result>WAo2xIg6</result>
</case> </case>
<case id="v1_type_short" parent="v1"> <case id="v1_type_short" parent="v1">
<siteType>GeneratedShort</siteType> <passwordType>GeneratedShort</passwordType>
<result>Jej2</result> <result>Jej2</result>
</case> </case>
<case id="v1_type_pin" parent="v1"> <case id="v1_type_pin" parent="v1">
<siteType>GeneratedPIN</siteType> <passwordType>GeneratedPIN</passwordType>
<result>7662</result> <result>7662</result>
</case> </case>
<case id="v1_type_name" parent="v1"> <case id="v1_type_name" parent="v1">
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>jejraquvo</result> <result>jejraquvo</result>
</case> </case>
<case id="v1_type_phrase" parent="v1"> <case id="v1_type_phrase" parent="v1">
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>jejr quv cabsibu tam</result> <result>jejr quv cabsibu tam</result>
</case> </case>
<case id="v1_counter_ceiling" parent="v1"> <case id="v1_counter_ceiling" parent="v1">
@ -230,45 +230,45 @@
<result>HahiVana2@Nole</result> <result>HahiVana2@Nole</result>
</case> </case>
<case id="v0_loginName" parent="v0"> <case id="v0_loginName" parent="v0">
<siteVariant>Login</siteVariant> <keyPurpose>Login</keyPurpose>
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>lozwajave</result> <result>lozwajave</result>
</case> </case>
<case id="v0_securityAnswer" parent="v0"> <case id="v0_securityAnswer" parent="v0">
<siteVariant>Answer</siteVariant> <keyPurpose>Answer</keyPurpose>
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>miy lirfijoja dubu</result> <result>miy lirfijoja dubu</result>
</case> </case>
<case id="v0_securityAnswer_context" parent="v0_securityAnswer"> <case id="v0_securityAnswer_context" parent="v0_securityAnswer">
<siteContext>question</siteContext> <keyContext>question</keyContext>
<result>movm bex gevrica jaf</result> <result>movm bex gevrica jaf</result>
</case> </case>
<case id="v0_type_maximum" parent="v0"> <case id="v0_type_maximum" parent="v0">
<siteType>GeneratedMaximum</siteType> <passwordType>GeneratedMaximum</passwordType>
<result>w1!3bA3icmRAc)SS@lwl</result> <result>w1!3bA3icmRAc)SS@lwl</result>
</case> </case>
<case id="v0_type_medium" parent="v0"> <case id="v0_type_medium" parent="v0">
<siteType>GeneratedMedium</siteType> <passwordType>GeneratedMedium</passwordType>
<result>Fej7]Jug</result> <result>Fej7]Jug</result>
</case> </case>
<case id="v0_type_basic" parent="v0"> <case id="v0_type_basic" parent="v0">
<siteType>GeneratedBasic</siteType> <passwordType>GeneratedBasic</passwordType>
<result>wvH7irC1</result> <result>wvH7irC1</result>
</case> </case>
<case id="v0_type_short" parent="v0"> <case id="v0_type_short" parent="v0">
<siteType>GeneratedShort</siteType> <passwordType>GeneratedShort</passwordType>
<result>Fej7</result> <result>Fej7</result>
</case> </case>
<case id="v0_type_pin" parent="v0"> <case id="v0_type_pin" parent="v0">
<siteType>GeneratedPIN</siteType> <passwordType>GeneratedPIN</passwordType>
<result>2117</result> <result>2117</result>
</case> </case>
<case id="v0_type_name" parent="v0"> <case id="v0_type_name" parent="v0">
<siteType>GeneratedName</siteType> <passwordType>GeneratedName</passwordType>
<result>fejrajugo</result> <result>fejrajugo</result>
</case> </case>
<case id="v0_type_phrase" parent="v0"> <case id="v0_type_phrase" parent="v0">
<siteType>GeneratedPhrase</siteType> <passwordType>GeneratedPhrase</passwordType>
<result>fejr jug gabsibu bax</result> <result>fejr jug gabsibu bax</result>
</case> </case>
<case id="v0_counter_ceiling" parent="v0"> <case id="v0_counter_ceiling" parent="v0">

View File

@ -331,20 +331,20 @@ static NSOperationQueue *_mpwQueue = nil;
- (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key { - (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedName withCounter:1 return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedName withCounter:1
variant:MPSiteVariantLogin context:nil usingKey:key]; variant:MPKeyPurposeIdentification context:nil usingKey:key];
} }
- (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter - (NSString *)generatePasswordForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
usingKey:(MPKey *)key { usingKey:(MPKey *)key {
return [self generateContentForSiteNamed:name ofType:type withCounter:counter return [self generateContentForSiteNamed:name ofType:type withCounter:counter
variant:MPSiteVariantPassword context:nil usingKey:key]; variant:MPKeyPurposeAuthentication context:nil usingKey:key];
} }
- (NSString *)generateAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key { - (NSString *)generateAnswerForSiteNamed:(NSString *)name onQuestion:(NSString *)question usingKey:(MPKey *)key {
return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedPhrase withCounter:1 return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedPhrase withCounter:1
variant:MPSiteVariantAnswer context:question usingKey:key]; variant:MPKeyPurposeRecovery context:question usingKey:key];
} }
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter - (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter

View File

@ -52,9 +52,9 @@ int main(int argc, char *const argv[]) {
const char *masterPassword = "banana colored duckling"; const char *masterPassword = "banana colored duckling";
const char *siteName = "masterpasswordapp.com"; const char *siteName = "masterpasswordapp.com";
const uint32_t siteCounter = 1; const uint32_t siteCounter = 1;
const MPSiteType siteType = MPSiteTypeDefault; const MPPasswordType passwordType = MPPasswordTypeDefault;
const MPSiteVariant siteVariant = MPSiteVariantPassword; const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
const char *siteContext = NULL; const char *keyContext = NULL;
struct timeval startTime; struct timeval startTime;
unsigned int iterations; unsigned int iterations;
float percent; float percent;
@ -112,9 +112,9 @@ int main(int argc, char *const argv[]) {
ftl( "Could not allocate master key: %d\n", errno ); ftl( "Could not allocate master key: %d\n", errno );
MPSiteKey siteKey = mpw_siteKey( MPSiteKey siteKey = mpw_siteKey(
masterKey, siteName, siteCounter, siteVariant, siteContext, MPAlgorithmVersionCurrent ); masterKey, siteName, siteCounter, keyPurpose, keyContext, MPAlgorithmVersionCurrent );
free( (void *)mpw_sitePassword( free( (void *)mpw_sitePassword(
siteKey, siteType, MPAlgorithmVersionCurrent ) ); siteKey, passwordType, MPAlgorithmVersionCurrent ) );
free( (void *)masterKey ); free( (void *)masterKey );
free( (void *)siteKey ); free( (void *)siteKey );

View File

@ -16,20 +16,18 @@
#include "mpw-marshall.h" #include "mpw-marshall.h"
#define MP_env_fullName "MP_FULLNAME" #define MP_env_fullName "MP_FULLNAME"
#define MP_env_siteType "MP_SITETYPE"
#define MP_env_siteCounter "MP_SITECOUNTER"
#define MP_env_algorithm "MP_ALGORITHM" #define MP_env_algorithm "MP_ALGORITHM"
static void usage() { static void usage() {
inf( "" inf( ""
"Usage: mpw [-u name] [-t type] [-c counter] [-a algorithm] [-V variant] [-C context] [-v|-q] [-h] site\n\n" ); "Usage: mpw [-u name] [-t type] [-c counter] [-a algorithm] [-p purpose] [-C context] [-v|-q] [-h] site\n\n" );
inf( "" inf( ""
" -u name Specify the full name of the user.\n" " -u name Specify the full name of the user.\n"
" Defaults to %s in env or prompts.\n\n", MP_env_fullName ); " Defaults to %s in env or prompts.\n\n", MP_env_fullName );
inf( "" inf( ""
" -t type Specify the password's template.\n" " -t type Specify the password's template.\n"
" Defaults to %s in env or 'long' for password, 'name' for login.\n" " Defaults to 'long' for auth, 'name' for ident and 'phrase' for recovery.\n"
" x, max, maximum | 20 characters, contains symbols.\n" " x, max, maximum | 20 characters, contains symbols.\n"
" l, long | Copy-friendly, 14 characters, contains symbols.\n" " l, long | Copy-friendly, 14 characters, contains symbols.\n"
" m, med, medium | Copy-friendly, 8 characters, contains symbols.\n" " m, med, medium | Copy-friendly, 8 characters, contains symbols.\n"
@ -37,26 +35,25 @@ static void usage() {
" s, short | Copy-friendly, 4 characters, no symbols.\n" " s, short | Copy-friendly, 4 characters, no symbols.\n"
" i, pin | 4 numbers.\n" " i, pin | 4 numbers.\n"
" n, name | 9 letter name.\n" " n, name | 9 letter name.\n"
" p, phrase | 20 character sentence.\n\n", MP_env_siteType ); " p, phrase | 20 character sentence.\n\n" );
inf( "" inf( ""
" -c counter The value of the counter.\n" " -c counter The value of the counter.\n"
" Defaults to %s in env or 1.\n\n", MP_env_siteCounter ); " Defaults to 1.\n\n" );
inf( "" inf( ""
" -a version The algorithm version to use.\n" " -a version The algorithm version to use.\n"
" Defaults to %s in env or %d.\n\n", MP_env_algorithm, MPAlgorithmVersionCurrent ); " Defaults to %s in env or %d.\n\n", MP_env_algorithm, MPAlgorithmVersionCurrent );
inf( "" inf( ""
" -V variant The kind of content to generate.\n" " -p purpose The purpose of the generated token.\n"
" Defaults to 'password'.\n" " Defaults to 'password'.\n"
" p, password | The password to log in with.\n" " a, auth | An authentication token such as a password.\n"
" l, login | The username to log in as.\n" " i, ident | An identification token such as a username.\n"
" a, answer | The answer to a security question.\n\n" ); " r, rec | A recovery token such as a security answer.\n\n" );
inf( "" inf( ""
" -C context A variant-specific context.\n" " -C context A purpose-specific context.\n"
" Defaults to empty.\n" " Defaults to empty.\n"
" -V p, password | Doesn't currently use a context.\n" " -p a, auth | -\n"
" -V l, login | Doesn't currently use a context.\n" " -p i, ident | -\n"
" -V a, answer | Empty for a universal site answer or\n" " -p r, rec | Most significant word in security question.\n\n" );
" | the most significant word(s) of the question.\n\n" );
inf( "" inf( ""
" -v Increase output verbosity (can be repeated).\n\n" ); " -v Increase output verbosity (can be repeated).\n\n" );
inf( "" inf( ""
@ -64,10 +61,8 @@ static void usage() {
inf( "" inf( ""
" ENVIRONMENT\n\n" " ENVIRONMENT\n\n"
" %-14s | The full name of the user (see -u).\n" " %-14s | The full name of the user (see -u).\n"
" %-14s | The default password template (see -t).\n"
" %-14s | The default counter value (see -c).\n"
" %-14s | The default algorithm version (see -a).\n\n", " %-14s | The default algorithm version (see -a).\n\n",
MP_env_fullName, MP_env_siteType, MP_env_siteCounter, MP_env_algorithm ); MP_env_fullName, MP_env_algorithm );
exit( 0 ); exit( 0 );
} }
@ -111,16 +106,15 @@ static char *getline_prompt(const char *prompt) {
int main(int argc, char *const argv[]) { int main(int argc, char *const argv[]) {
// Master Password defaults. // Master Password defaults.
const char *fullName = NULL, *masterPassword = NULL, *siteName = NULL; const char *fullName = NULL, *masterPassword = NULL, *siteName = NULL, *keyContext = NULL;
MPSiteType siteType = MPSiteTypeDefault; MPPasswordType passwordType = MPPasswordTypeDefault;
MPSiteVariant siteVariant = MPSiteVariantPassword; MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent; MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
uint32_t siteCounter = 1; uint32_t siteCounter = 1;
// Read the environment. // Read the environment.
const char *fullNameArg = getenv( MP_env_fullName ), *masterPasswordArg = NULL, *siteNameArg = NULL; const char *fullNameArg = getenv( MP_env_fullName ), *masterPasswordArg = NULL, *siteNameArg = NULL;
const char *siteTypeArg = getenv( MP_env_siteType ), *siteVariantArg = NULL, *siteContextArg = NULL; const char *passwordTypeArg = NULL, *keyPurposeArg = NULL, *keyContextArg = NULL, *siteCounterArg = NULL;
const char *siteCounterArg = getenv( MP_env_siteCounter );
const char *algorithmVersionArg = getenv( MP_env_algorithm ); const char *algorithmVersionArg = getenv( MP_env_algorithm );
// Read the command-line options. // Read the command-line options.
@ -134,19 +128,19 @@ int main(int argc, char *const argv[]) {
masterPasswordArg = optarg; masterPasswordArg = optarg;
break; break;
case 't': case 't':
siteTypeArg = optarg; passwordTypeArg = optarg;
break; break;
case 'c': case 'c':
siteCounterArg = optarg; siteCounterArg = optarg;
break; break;
case 'V': case 'p':
siteVariantArg = optarg; keyPurposeArg = optarg;
break; break;
case 'a': case 'a':
algorithmVersionArg = optarg; algorithmVersionArg = optarg;
break; break;
case 'C': case 'C':
siteContextArg = optarg; keyContextArg = optarg;
break; break;
case 'v': case 'v':
++mpw_verbosity; ++mpw_verbosity;
@ -183,9 +177,9 @@ int main(int argc, char *const argv[]) {
fullNameArg = fullNameArg && strlen( fullNameArg )? fullNameArg: NULL; fullNameArg = fullNameArg && strlen( fullNameArg )? fullNameArg: NULL;
masterPasswordArg = masterPasswordArg && strlen( masterPasswordArg )? masterPasswordArg: NULL; masterPasswordArg = masterPasswordArg && strlen( masterPasswordArg )? masterPasswordArg: NULL;
siteNameArg = siteNameArg && strlen( siteNameArg )? siteNameArg: NULL; siteNameArg = siteNameArg && strlen( siteNameArg )? siteNameArg: NULL;
siteTypeArg = siteTypeArg && strlen( siteTypeArg )? siteTypeArg: NULL; passwordTypeArg = passwordTypeArg && strlen( passwordTypeArg )? passwordTypeArg: NULL;
siteVariantArg = siteVariantArg && strlen( siteVariantArg )? siteVariantArg: NULL; keyPurposeArg = keyPurposeArg && strlen( keyPurposeArg )? keyPurposeArg: NULL;
siteContextArg = siteContextArg && strlen( siteContextArg )? siteContextArg: NULL; keyContextArg = keyContextArg && strlen( keyContextArg )? keyContextArg: NULL;
siteCounterArg = siteCounterArg && strlen( siteCounterArg )? siteCounterArg: NULL; siteCounterArg = siteCounterArg && strlen( siteCounterArg )? siteCounterArg: NULL;
algorithmVersionArg = algorithmVersionArg && strlen( algorithmVersionArg )? algorithmVersionArg: NULL; algorithmVersionArg = algorithmVersionArg && strlen( algorithmVersionArg )? algorithmVersionArg: NULL;
@ -239,11 +233,11 @@ int main(int argc, char *const argv[]) {
fullName = strdup( user->name ); fullName = strdup( user->name );
masterPassword = strdup( user->masterPassword ); masterPassword = strdup( user->masterPassword );
algorithmVersion = user->algorithm; algorithmVersion = user->algorithm;
siteType = user->defaultType; passwordType = user->defaultType;
for (size_t s = 0; s < user->sites_count; ++s) { for (size_t s = 0; s < user->sites_count; ++s) {
MPMarshalledSite site = user->sites[s]; MPMarshalledSite site = user->sites[s];
if (strcmp( siteName, site.name ) == 0) { if (strcmp( siteName, site.name ) == 0) {
siteType = site.type; passwordType = site.type;
siteCounter = site.counter; siteCounter = site.counter;
algorithmVersion = site.algorithm; algorithmVersion = site.algorithm;
break; break;
@ -285,14 +279,16 @@ int main(int argc, char *const argv[]) {
ftl( "Invalid site counter: %s\n", siteCounterArg ); ftl( "Invalid site counter: %s\n", siteCounterArg );
siteCounter = (uint32_t)siteCounterInt; siteCounter = (uint32_t)siteCounterInt;
} }
if (siteVariantArg) if (keyPurposeArg)
siteVariant = mpw_variantWithName( siteVariantArg ); keyPurpose = mpw_purposeWithName( keyPurposeArg );
if (siteVariant == MPSiteVariantLogin) if (keyPurpose == MPKeyPurposeIdentification)
siteType = MPSiteTypeGeneratedName; passwordType = MPPasswordTypeGeneratedName;
if (siteVariant == MPSiteVariantAnswer) if (keyPurpose == MPKeyPurposeRecovery)
siteType = MPSiteTypeGeneratedPhrase; passwordType = MPPasswordTypeGeneratedPhrase;
if (siteTypeArg) if (passwordTypeArg)
siteType = mpw_typeWithName( siteTypeArg ); passwordType = mpw_typeWithName( passwordTypeArg );
if (keyContextArg)
keyContext = strdup( keyContextArg );
// Summarize operation. // Summarize operation.
const char *identicon = mpw_identicon( fullName, masterPassword ); const char *identicon = mpw_identicon( fullName, masterPassword );
@ -303,7 +299,7 @@ int main(int argc, char *const argv[]) {
trc( "masterPassword : %s\n", masterPassword ); trc( "masterPassword : %s\n", masterPassword );
dbg( "identicon : %s\n", identicon ); dbg( "identicon : %s\n", identicon );
dbg( "siteName : %s\n", siteName ); dbg( "siteName : %s\n", siteName );
dbg( "siteType : %u\n", siteType ); dbg( "passwordType : %u\n", passwordType );
dbg( "algorithmVersion : %u\n", algorithmVersion ); dbg( "algorithmVersion : %u\n", algorithmVersion );
dbg( "siteCounter : %u\n", siteCounter ); dbg( "siteCounter : %u\n", siteCounter );
dbg( "-----------------\n\n" ); dbg( "-----------------\n\n" );
@ -318,11 +314,12 @@ int main(int argc, char *const argv[]) {
if (!masterKey) if (!masterKey)
ftl( "Couldn't derive master key." ); ftl( "Couldn't derive master key." );
MPSiteKey siteKey = mpw_siteKey( masterKey, siteName, siteCounter, siteVariant, siteContextArg, algorithmVersion ); MPSiteKey siteKey = mpw_siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext, algorithmVersion );
const char *sitePassword = mpw_sitePassword(siteKey, siteType, algorithmVersion ); const char *sitePassword = mpw_sitePassword(siteKey, passwordType, algorithmVersion );
mpw_free( masterKey, MPMasterKeySize ); mpw_free( masterKey, MPMasterKeySize );
mpw_free( siteKey, MPSiteKeySize ); mpw_free( siteKey, MPSiteKeySize );
mpw_free_string( siteName ); mpw_free_string( siteName );
mpw_free_string( keyContext );
if (!sitePassword) if (!sitePassword)
ftl( "Couldn't derive site password." ); ftl( "Couldn't derive site password." );

View File

@ -1,5 +1,3 @@
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -30,13 +28,13 @@ int main(int argc, char *const argv[]) {
xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" ); xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" );
xmlChar *siteName = mpw_xmlTestCaseString( testCase, "siteName" ); xmlChar *siteName = mpw_xmlTestCaseString( testCase, "siteName" );
uint32_t siteCounter = mpw_xmlTestCaseInteger( testCase, "siteCounter" ); uint32_t siteCounter = mpw_xmlTestCaseInteger( testCase, "siteCounter" );
xmlChar *siteTypeString = mpw_xmlTestCaseString( testCase, "siteType" ); xmlChar *passwordTypeString = mpw_xmlTestCaseString( testCase, "passwordType" );
xmlChar *siteVariantString = mpw_xmlTestCaseString( testCase, "siteVariant" ); xmlChar *keyPurposeString = mpw_xmlTestCaseString( testCase, "keyPurpose" );
xmlChar *siteContext = mpw_xmlTestCaseString( testCase, "siteContext" ); xmlChar *keyContext = mpw_xmlTestCaseString( testCase, "keyContext" );
xmlChar *result = mpw_xmlTestCaseString( testCase, "result" ); xmlChar *result = mpw_xmlTestCaseString( testCase, "result" );
MPSiteType siteType = mpw_typeWithName( (char *)siteTypeString ); MPPasswordType siteType = mpw_typeWithName( (char *)passwordTypeString );
MPSiteVariant siteVariant = mpw_variantWithName( (char *)siteVariantString ); MPKeyPurpose siteVariant = mpw_purposeWithName( (char *)keyPurposeString );
// Run the test case. // Run the test case.
fprintf( stdout, "test case %s... ", id ); fprintf( stdout, "test case %s... ", id );
@ -53,7 +51,7 @@ int main(int argc, char *const argv[]) {
// 2. calculate the site password. // 2. calculate the site password.
MPSiteKey siteKey = mpw_siteKey( MPSiteKey siteKey = mpw_siteKey(
masterKey, (char *)siteName, siteCounter, siteVariant, (char *)siteContext, algorithm ); masterKey, (char *)siteName, siteCounter, siteVariant, (char *)keyContext, algorithm );
const char *sitePassword = mpw_sitePassword( const char *sitePassword = mpw_sitePassword(
siteKey, siteType, algorithm ); siteKey, siteType, algorithm );
mpw_free( masterKey, MPMasterKeySize ); mpw_free( masterKey, MPMasterKeySize );
@ -77,9 +75,9 @@ int main(int argc, char *const argv[]) {
xmlFree( masterPassword ); xmlFree( masterPassword );
xmlFree( keyID ); xmlFree( keyID );
xmlFree( siteName ); xmlFree( siteName );
xmlFree( siteTypeString ); xmlFree( passwordTypeString );
xmlFree( siteVariantString ); xmlFree( keyPurposeString );
xmlFree( siteContext ); xmlFree( keyContext );
xmlFree( result ); xmlFree( result );
} }