2
0

passwordType -> resultType, add derived class and key type.

This commit is contained in:
Maarten Billemont 2017-08-10 12:30:42 -04:00
parent b1985a2bf2
commit 4f7c28563d
17 changed files with 519 additions and 379 deletions

View File

@ -72,69 +72,98 @@ MPSiteKey mpw_siteKey(
} }
} }
const char *mpw_sitePassword( const char *mpw_siteResult(
MPSiteKey siteKey, const MPPasswordType passwordType, const MPAlgorithmVersion algorithmVersion) { MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *resultParam,
const MPAlgorithmVersion algorithmVersion) {
trc( "-- mpw_sitePassword (algorithm: %u)\n", algorithmVersion ); MPSiteKey siteKey = mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
trc( "passwordType: %d (%s)\n", passwordType, mpw_nameForType( passwordType ) );
if (!siteKey) if (!siteKey)
return NULL; return NULL;
trc( "-- mpw_siteResult (algorithm: %u)\n", algorithmVersion );
trc( "resultType: %d (%s)\n", resultType, mpw_nameForType( resultType ) );
trc( "resultParam: %s\n", resultParam );
char *sitePassword = NULL;
if (resultType & MPResultTypeClassTemplate) {
switch (algorithmVersion) { switch (algorithmVersion) {
case MPAlgorithmVersion0: case MPAlgorithmVersion0:
return mpw_sitePassword_v0( siteKey, passwordType ); return mpw_sitePasswordFromTemplate_v0( masterKey, siteKey, resultType, resultParam );
case MPAlgorithmVersion1: case MPAlgorithmVersion1:
return mpw_sitePassword_v1( siteKey, passwordType ); return mpw_sitePasswordFromTemplate_v1( masterKey, siteKey, resultType, resultParam );
case MPAlgorithmVersion2: case MPAlgorithmVersion2:
return mpw_sitePassword_v2( siteKey, passwordType ); return mpw_sitePasswordFromTemplate_v2( masterKey, siteKey, resultType, resultParam );
case MPAlgorithmVersion3: case MPAlgorithmVersion3:
return mpw_sitePassword_v3( siteKey, passwordType ); return mpw_sitePasswordFromTemplate_v3( masterKey, siteKey, resultType, resultParam );
default: default:
err( "Unsupported version: %d\n", algorithmVersion ); err( "Unsupported version: %d\n", algorithmVersion );
return NULL; return NULL;
} }
} }
else if (resultType & MPResultTypeClassState) {
const char *mpw_encrypt( switch (algorithmVersion) {
MPMasterKey masterKey, const char *plainText, const MPAlgorithmVersion algorithmVersion) { case MPAlgorithmVersion0:
return mpw_sitePasswordFromCrypt_v0( masterKey, siteKey, resultType, resultParam );
trc( "-- mpw_encrypt (algorithm: %u)\n", algorithmVersion ); case MPAlgorithmVersion1:
trc( "plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) ); return mpw_sitePasswordFromCrypt_v1( masterKey, siteKey, resultType, resultParam );
if (!masterKey || !plainText) case MPAlgorithmVersion2:
return NULL; return mpw_sitePasswordFromCrypt_v2( masterKey, siteKey, resultType, resultParam );
case MPAlgorithmVersion3:
switch (algorithmVersion) { return mpw_sitePasswordFromCrypt_v3( masterKey, siteKey, resultType, resultParam );
case MPAlgorithmVersion0: default:
return mpw_encrypt_v0( masterKey, plainText ); err( "Unsupported version: %d\n", algorithmVersion );
case MPAlgorithmVersion1: return NULL;
return mpw_encrypt_v1( masterKey, plainText ); }
case MPAlgorithmVersion2: }
return mpw_encrypt_v2( masterKey, plainText ); else if (resultType & MPResultTypeClassDerive) {
case MPAlgorithmVersion3: switch (algorithmVersion) {
return mpw_encrypt_v3( masterKey, plainText ); case MPAlgorithmVersion0:
default: return mpw_sitePasswordFromDerive_v0( masterKey, siteKey, resultType, resultParam );
err( "Unsupported version: %d\n", algorithmVersion ); case MPAlgorithmVersion1:
return NULL; return mpw_sitePasswordFromDerive_v1( masterKey, siteKey, resultType, resultParam );
} case MPAlgorithmVersion2:
} return mpw_sitePasswordFromDerive_v2( masterKey, siteKey, resultType, resultParam );
case MPAlgorithmVersion3:
const char *mpw_decrypt( return mpw_sitePasswordFromDerive_v3( masterKey, siteKey, resultType, resultParam );
MPMasterKey masterKey, const char *cipherText, const MPAlgorithmVersion algorithmVersion) { default:
err( "Unsupported version: %d\n", algorithmVersion );
trc( "-- mpw_decrypt (algorithm: %u)\n", algorithmVersion ); return NULL;
trc( "cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) ); }
if (!masterKey || !cipherText) }
return NULL; else {
err( "Unsupported password type: %d\n", resultType );
switch (algorithmVersion) { }
case MPAlgorithmVersion0:
return mpw_decrypt_v0( masterKey, cipherText ); return sitePassword;
case MPAlgorithmVersion1: }
return mpw_decrypt_v1( masterKey, cipherText );
case MPAlgorithmVersion2: const char *mpw_siteState(
return mpw_decrypt_v2( masterKey, cipherText ); MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
case MPAlgorithmVersion3: const MPKeyPurpose keyPurpose, const char *keyContext,
return mpw_decrypt_v3( masterKey, cipherText ); const MPResultType resultType, const char *state,
const MPAlgorithmVersion algorithmVersion) {
MPSiteKey siteKey = mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
if (!siteKey)
return NULL;
trc( "-- mpw_siteState (algorithm: %u)\n", algorithmVersion );
trc( "resultType: %d (%s)\n", resultType, mpw_nameForType( resultType ) );
trc( "state: %s\n", state );
if (!masterKey || !state)
return NULL;
switch (algorithmVersion) {
case MPAlgorithmVersion0:
return mpw_siteState_v0( masterKey, siteKey, resultType, state );
case MPAlgorithmVersion1:
return mpw_siteState_v1( masterKey, siteKey, resultType, state );
case MPAlgorithmVersion2:
return mpw_siteState_v2( masterKey, siteKey, resultType, state );
case MPAlgorithmVersion3:
return mpw_siteState_v3( masterKey, siteKey, resultType, state );
default: default:
err( "Unsupported version: %d\n", algorithmVersion ); err( "Unsupported version: %d\n", algorithmVersion );
return NULL; return NULL;

View File

@ -50,17 +50,18 @@ MPSiteKey mpw_siteKey(
/** 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_siteResult(
MPSiteKey siteKey, const MPPasswordType passwordType, const MPAlgorithmVersion algorithmVersion); MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *resultParam,
const MPAlgorithmVersion algorithmVersion);
/** Perform symmetric encryption on a secret token's plainText. /** Perform symmetric encryption on a secret token's plainText.
* @return The newly allocated cipherText of the secret token encrypted by the masterKey. */ * @return The newly allocated cipherText of the secret token encrypted by the masterKey. */
const char *mpw_encrypt( const char *mpw_siteState(
MPMasterKey masterKey, const char *plainText, const MPAlgorithmVersion algorithmVersion); MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
/** Perform symmetric decryption on a secret token's cipherText. const MPResultType resultType, const char *state,
* @return The newly allocated plainText of the secret token decrypted by the masterKey. */ const MPAlgorithmVersion algorithmVersion);
const char *mpw_decrypt(
MPMasterKey masterKey, const char *cipherText, const MPAlgorithmVersion algorithmVersion);
#endif // _MPW_ALGORITHM_H #endif // _MPW_ALGORITHM_H

View File

@ -29,7 +29,7 @@
#define MP_p 2U #define MP_p 2U
// Algorithm version helpers. // Algorithm version helpers.
static const char *mpw_templateForType_v0(MPPasswordType type, uint16_t seedByte) { static const char *mpw_templateForType_v0(MPResultType 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 );
@ -70,7 +70,7 @@ static MPMasterKey mpw_masterKey_v0(
// Calculate the master key. // Calculate the master key.
trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", 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 ); MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
mpw_free( masterKeySalt, masterKeySaltSize ); mpw_free( masterKeySalt, masterKeySaltSize );
if (!masterKey) { if (!masterKey) {
err( "Could not allocate master key: %s\n", strerror( errno ) ); err( "Could not allocate master key: %s\n", strerror( errno ) );
@ -113,10 +113,10 @@ static MPSiteKey mpw_siteKey_v0(
trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n", trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n",
mpw_id_buf( masterKey, MPMasterKeySize ) ); mpw_id_buf( masterKey, MPMasterKeySize ) );
MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
mpw_free( siteSalt, siteSaltSize ); mpw_free( siteSalt, siteSaltSize );
if (!siteKey) { if (!siteKey) {
err( "Could not allocate site key: %s\n", strerror( errno ) ); err( "Could not derive site key: %s\n", strerror( errno ) );
return NULL; return NULL;
} }
trc( " => siteKey.id: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) ); trc( " => siteKey.id: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
@ -124,12 +124,12 @@ static MPSiteKey mpw_siteKey_v0(
return siteKey; return siteKey;
} }
static const char *mpw_sitePassword_v0( static const char *mpw_sitePasswordFromTemplate_v0(
MPSiteKey siteKey, const MPPasswordType passwordType) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
// Determine the template. // Determine the template.
const char *_siteKey = (const char *)siteKey; const char *_siteKey = (const char *)siteKey;
const char *template = mpw_templateForType_v0( passwordType, htons( _siteKey[0] ) ); const char *template = mpw_templateForType_v0( resultType, htons( _siteKey[0] ) );
trc( "template: %u => %s\n", htons( _siteKey[0] ), template ); trc( "template: %u => %s\n", htons( _siteKey[0] ), template );
if (!template) if (!template)
return NULL; return NULL;
@ -139,7 +139,7 @@ static const char *mpw_sitePassword_v0(
} }
// Encode the password from the seed using the template. // Encode the password from the seed using the template.
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) ); char *sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
for (size_t c = 0; c < strlen( template ); ++c) { for (size_t c = 0; c < strlen( template ); ++c) {
sitePassword[c] = mpw_characterFromClass_v0( template[c], htons( _siteKey[c + 1] ) ); sitePassword[c] = mpw_characterFromClass_v0( template[c], htons( _siteKey[c + 1] ) );
trc( " - class: %c, index: %5u (0x%02hX) => character: %c\n", trc( " - class: %c, index: %5u (0x%02hX) => character: %c\n",
@ -150,8 +150,80 @@ static const char *mpw_sitePassword_v0(
return sitePassword; return sitePassword;
} }
const char *mpw_encrypt_v0( static const char *mpw_sitePasswordFromCrypt_v0(
MPMasterKey masterKey, const char *plainText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
if (!cipherText) {
err( "Missing encrypted state.\n" );
return NULL;
}
// Base64-decode
uint8_t *cipherBuf = calloc( 1, mpw_base64_decode_max( cipherText ) );
size_t bufSize = (size_t)mpw_base64_decode( cipherBuf, cipherText );
if ((int)bufSize < 0) {
err( "Base64 decoding error." );
mpw_free( cipherBuf, mpw_base64_decode_max( cipherText ) );
return NULL;
}
trc( "b64 decoded: %zu bytes = %s\n", bufSize, mpw_hex( cipherBuf, bufSize ) );
// Decrypt
const uint8_t *plainBytes = mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize );
const char *plainText = strndup( (char *)plainBytes, bufSize );
mpw_free( plainBytes, bufSize );
if (!plainText)
err( "AES decryption error: %s\n", strerror( errno ) );
trc( "decrypted -> plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) );
mpw_free( cipherBuf, bufSize );
return plainText;
}
static const char *mpw_sitePasswordFromDerive_v0(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
switch (resultType) {
case MPResultTypeDeriveKey: {
if (!resultParam) {
err( "Missing key size parameter.\n" );
return NULL;
}
int resultParamInt = atoi( resultParam );
if (resultParamInt <= 0 || resultParamInt > UINT16_MAX || resultParamInt % 8 != 0) {
err( "Parameter is not a valid key size: %s\n", resultParam );
return NULL;
}
uint16_t keySize = (uint16_t)(resultParamInt / 8);
trc( "keySize: %u\n", keySize );
// Derive key
const uint8_t *resultKey = mpw_kdf_blake2b( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL );
if (!resultKey) {
err( "Could not derive result key: %s\n", strerror( errno ) );
return NULL;
}
// Base64-encode
size_t b64Max = mpw_base64_encode_max( keySize );
char *sitePassword = calloc( 1, b64Max + 1 );
if (mpw_base64_encode( sitePassword, resultKey, keySize ) < 0) {
err( "Base64 encoding error." );
mpw_free_string( sitePassword );
sitePassword = NULL;
}
trc( "b64 encoded -> key.id: %s\n", mpw_id_buf( sitePassword, strlen( sitePassword ) ) );
return sitePassword;
}
default:
err( "Unsupported derived password type: %d\n", resultType );
return NULL;
}
}
static const char *mpw_siteState_v0(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *plainText) {
// Encrypt // Encrypt
size_t bufSize = strlen( plainText ); size_t bufSize = strlen( plainText );
@ -175,28 +247,3 @@ const char *mpw_encrypt_v0(
return cipherText; return cipherText;
} }
const char *mpw_decrypt_v0(
MPMasterKey masterKey, const char *cipherText) {
// Base64-decode
uint8_t *cipherBuf = calloc( 1, mpw_base64_decode_max( cipherText ) );
size_t bufSize = (size_t)mpw_base64_decode( cipherBuf, cipherText );
if ((int)bufSize < 0) {
err( "Base64 decoding error." );
mpw_free( cipherBuf, mpw_base64_decode_max( cipherText ) );
return NULL;
}
trc( "b64 decoded: %zu bytes = %s\n", bufSize, mpw_hex( cipherBuf, bufSize ) );
// Decrypt
const uint8_t *plainBytes = mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize );
const char *plainText = strndup( (char *)plainBytes, bufSize );
mpw_free( plainBytes, bufSize );
if (!plainText)
err( "AES decryption error: %s\n", strerror( errno ) );
trc( "decrypted -> plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) );
mpw_free( cipherBuf, bufSize );
return plainText;
}

View File

@ -33,10 +33,12 @@ MPMasterKey mpw_masterKey_v0(
MPSiteKey mpw_siteKey_v0( MPSiteKey mpw_siteKey_v0(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext); const MPKeyPurpose keyPurpose, const char *keyContext);
const char *mpw_encrypt_v0( const char *mpw_sitePasswordFromCrypt_v0(
MPMasterKey masterKey, const char *plainText); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
const char *mpw_decrypt_v0( const char *mpw_sitePasswordFromDerive_v0(
MPMasterKey masterKey, const char *cipherText); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_siteState_v0(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state);
// Algorithm version overrides. // Algorithm version overrides.
static MPMasterKey mpw_masterKey_v1( static MPMasterKey mpw_masterKey_v1(
@ -52,11 +54,11 @@ static MPSiteKey mpw_siteKey_v1(
return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext ); return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
} }
static const char *mpw_sitePassword_v1( static const char *mpw_sitePasswordFromTemplate_v1(
MPSiteKey siteKey, const MPPasswordType passwordType) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
// Determine the template. // Determine the template.
const char *template = mpw_templateForType( passwordType, siteKey[0] ); const char *template = mpw_templateForType( resultType, siteKey[0] );
trc( "template: %u => %s\n", siteKey[0], template ); trc( "template: %u => %s\n", siteKey[0], template );
if (!template) if (!template)
return NULL; return NULL;
@ -77,14 +79,20 @@ static const char *mpw_sitePassword_v1(
return sitePassword; return sitePassword;
} }
static const char *mpw_encrypt_v1( static const char *mpw_sitePasswordFromCrypt_v1(
MPMasterKey masterKey, const char *plainText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
return mpw_encrypt_v0( masterKey, plainText ); return mpw_sitePasswordFromCrypt_v0( masterKey, siteKey, resultType, cipherText );
} }
static const char *mpw_decrypt_v1( static const char *mpw_sitePasswordFromDerive_v1(
MPMasterKey masterKey, const char *cipherText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
return mpw_decrypt_v0( masterKey, cipherText ); return mpw_sitePasswordFromDerive_v0( masterKey, siteKey, resultType, resultParam );
}
static const char *mpw_siteState_v1(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state) {
return mpw_siteState_v0( masterKey, siteKey, resultType, state );
} }

View File

@ -30,12 +30,14 @@
// Inherited functions. // Inherited functions.
MPMasterKey mpw_masterKey_v1( MPMasterKey mpw_masterKey_v1(
const char *fullName, const char *masterPassword); const char *fullName, const char *masterPassword);
const char *mpw_sitePassword_v1( const char *mpw_sitePasswordFromTemplate_v1(
MPSiteKey siteKey, const MPPasswordType passwordType); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_encrypt_v1( const char *mpw_sitePasswordFromCrypt_v1(
MPMasterKey masterKey, const char *plainText); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
const char *mpw_decrypt_v1( const char *mpw_sitePasswordFromDerive_v1(
MPMasterKey masterKey, const char *cipherText); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_siteState_v1(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state);
// Algorithm version overrides. // Algorithm version overrides.
static MPMasterKey mpw_masterKey_v2( static MPMasterKey mpw_masterKey_v2(
@ -76,7 +78,7 @@ static MPSiteKey mpw_siteKey_v2(
trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n", trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n",
mpw_id_buf( masterKey, MPMasterKeySize ) ); mpw_id_buf( masterKey, MPMasterKeySize ) );
MPSiteKey siteKey = mpw_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize );
mpw_free( siteSalt, siteSaltSize ); mpw_free( siteSalt, siteSaltSize );
if (!siteKey) { if (!siteKey) {
err( "Could not allocate site key: %s\n", strerror( errno ) ); err( "Could not allocate site key: %s\n", strerror( errno ) );
@ -87,20 +89,26 @@ static MPSiteKey mpw_siteKey_v2(
return siteKey; return siteKey;
} }
static const char *mpw_sitePassword_v2( static const char *mpw_sitePasswordFromTemplate_v2(
MPSiteKey siteKey, const MPPasswordType passwordType) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
return mpw_sitePassword_v1( siteKey, passwordType ); return mpw_sitePasswordFromTemplate_v1( masterKey, siteKey, resultType, resultParam );
} }
static const char *mpw_encrypt_v2( static const char *mpw_sitePasswordFromCrypt_v2(
MPMasterKey masterKey, const char *plainText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
return mpw_encrypt_v1( masterKey, plainText ); return mpw_sitePasswordFromCrypt_v1( masterKey, siteKey, resultType, cipherText );
} }
static const char *mpw_decrypt_v2( static const char *mpw_sitePasswordFromDerive_v2(
MPMasterKey masterKey, const char *cipherText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
return mpw_decrypt_v1( masterKey, cipherText ); return mpw_sitePasswordFromDerive_v1( masterKey, siteKey, resultType, resultParam );
}
static const char *mpw_siteState_v2(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state) {
return mpw_siteState_v1( masterKey, siteKey, resultType, state );
} }

View File

@ -31,12 +31,14 @@
MPSiteKey mpw_siteKey_v2( MPSiteKey mpw_siteKey_v2(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext); const MPKeyPurpose keyPurpose, const char *keyContext);
const char *mpw_sitePassword_v2( const char *mpw_sitePasswordFromTemplate_v2(
MPSiteKey siteKey, const MPPasswordType passwordType); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_encrypt_v2( const char *mpw_sitePasswordFromCrypt_v2(
MPMasterKey masterKey, const char *plainText); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
const char *mpw_decrypt_v2( const char *mpw_sitePasswordFromDerive_v2(
MPMasterKey masterKey, const char *cipherText); MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_siteState_v2(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state);
// Algorithm version overrides. // Algorithm version overrides.
static MPMasterKey mpw_masterKey_v3( static MPMasterKey mpw_masterKey_v3(
@ -61,7 +63,7 @@ static MPMasterKey mpw_masterKey_v3(
// Calculate the master key. // Calculate the master key.
trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )\n", 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 ); MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
mpw_free( masterKeySalt, masterKeySaltSize ); mpw_free( masterKeySalt, masterKeySaltSize );
if (!masterKey) { if (!masterKey) {
err( "Could not allocate master key: %s\n", strerror( errno ) ); err( "Could not allocate master key: %s\n", strerror( errno ) );
@ -73,26 +75,32 @@ static MPMasterKey mpw_masterKey_v3(
} }
static MPSiteKey mpw_siteKey_v3( static MPSiteKey mpw_siteKey_v3(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, const MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext) { const MPKeyPurpose keyPurpose, const char *keyContext) {
return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext ); return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );
} }
static const char *mpw_sitePassword_v3( static const char *mpw_sitePasswordFromTemplate_v3(
MPSiteKey siteKey, const MPPasswordType passwordType) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
return mpw_sitePassword_v2( siteKey, passwordType ); return mpw_sitePasswordFromTemplate_v2( masterKey, siteKey, resultType, resultParam );
} }
static const char *mpw_encrypt_v3( static const char *mpw_sitePasswordFromCrypt_v3(
MPMasterKey masterKey, const char *plainText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText) {
return mpw_encrypt_v2( masterKey, plainText ); return mpw_sitePasswordFromCrypt_v2( masterKey, siteKey, resultType, cipherText );
} }
static const char *mpw_decrypt_v3( static const char *mpw_sitePasswordFromDerive_v3(
MPMasterKey masterKey, const char *cipherText) { MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
return mpw_decrypt_v2( masterKey, cipherText ); return mpw_sitePasswordFromDerive_v2( masterKey, siteKey, resultType, resultParam );
}
static const char *mpw_siteState_v3(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *state) {
return mpw_siteState_v2( masterKey, siteKey, resultType, state );
} }

View File

@ -39,7 +39,7 @@ MPMarshalledUser *mpw_marshall_user(
.redacted = true, .redacted = true,
.avatar = 0, .avatar = 0,
.defaultType = MPPasswordTypeDefault, .defaultType = MPResultTypeDefault,
.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 *user, const char *siteName, const MPPasswordType passwordType, MPMarshalledUser *user, const char *siteName, const MPResultType resultType,
const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) { const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) {
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count )) if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count ))
@ -59,7 +59,7 @@ MPMarshalledSite *mpw_marshall_site(
*site = (MPMarshalledSite){ *site = (MPMarshalledSite){
.name = strdup( siteName ), .name = strdup( siteName ),
.content = NULL, .content = NULL,
.type = passwordType, .type = resultType,
.counter = siteCounter, .counter = siteCounter,
.algorithm = algorithmVersion, .algorithm = algorithmVersion,
@ -171,13 +171,9 @@ static bool mpw_marshall_write_flat(
return false; return false;
} }
if (site->type & MPPasswordTypeClassGenerated) { if (site->type & MPResultTypeClassTemplate)
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, site->counter, MPKeyPurposeAuthentication, NULL, site->algorithm ); content = mpw_siteResult( masterKey, site->name, site->counter,
content = mpw_sitePassword( siteKey, site->type, site->algorithm ); MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm );
mpw_free( siteKey, MPSiteKeySize );
}
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
content = mpw_decrypt( masterKey, site->content, site->algorithm );
} }
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content )) else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
// Redacted // Redacted
@ -255,13 +251,9 @@ static bool mpw_marshall_write_json(
return false; return false;
} }
if (site->type & MPPasswordTypeClassGenerated) { if (site->type & MPResultTypeClassTemplate)
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, site->counter, MPKeyPurposeAuthentication, NULL, site->algorithm ); content = mpw_siteResult( masterKey, site->name, site->counter,
content = mpw_sitePassword( siteKey, site->type, site->algorithm ); MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm );
mpw_free( siteKey, MPSiteKeySize );
}
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
content = mpw_decrypt( masterKey, site->content, site->algorithm );
} }
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content )) else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
// Redacted // Redacted
@ -294,10 +286,8 @@ static bool mpw_marshall_write_json(
if (!user->redacted) { if (!user->redacted) {
// Clear Text // Clear Text
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, const char *answer = mpw_siteResult( masterKey, site->name, MPCounterValueInitial,
MPCounterValueInitial, MPKeyPurposeRecovery, question->keyword, site->algorithm ); MPKeyPurposeRecovery, question->keyword, MPResultTypeTemplatePhrase, NULL, site->algorithm );
const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site->algorithm );
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 ) );
} }
@ -327,10 +317,10 @@ bool mpw_marshall_write(
return mpw_marshall_write_flat( out, user, error ); return mpw_marshall_write_flat( out, user, error );
case MPMarshallFormatJSON: case MPMarshallFormatJSON:
return mpw_marshall_write_json( out, user, error ); return mpw_marshall_write_json( out, user, error );
} default:
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) }; *error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) };
return false; return false;
}
} }
static MPMarshalledUser *mpw_marshall_read_flat( static MPMarshalledUser *mpw_marshall_read_flat(
@ -344,7 +334,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
unsigned int format = 0, avatar = 0; unsigned int format = 0, avatar = 0;
char *fullName = NULL, *keyID = NULL; char *fullName = NULL, *keyID = NULL;
MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1; MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1;
MPPasswordType defaultType = MPPasswordTypeDefault; MPResultType defaultType = MPResultTypeDefault;
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) {
@ -395,11 +385,11 @@ static MPMarshalledUser *mpw_marshall_read_flat(
} }
if (strcmp( headerName, "Default Type" ) == 0) { if (strcmp( headerName, "Default Type" ) == 0) {
int value = atoi( headerValue ); int value = atoi( headerValue );
if (!mpw_nameForType( (MPPasswordType)value )) { if (!mpw_nameForType( (MPResultType)value )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid user default type: %s", headerValue ) }; *error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid user default type: %s", headerValue ) };
return NULL; return NULL;
} }
defaultType = (MPPasswordType)value; defaultType = (MPResultType)value;
} }
if (strcmp( headerName, "Passwords" ) == 0) if (strcmp( headerName, "Passwords" ) == 0)
importRedacted = strcmp( headerValue, "VISIBLE" ) != 0; importRedacted = strcmp( headerValue, "VISIBLE" ) != 0;
@ -477,7 +467,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
} }
if (siteName && str_type && str_counter && str_algorithm && str_uses && str_lastUsed) { if (siteName && str_type && str_counter && str_algorithm && str_uses && str_lastUsed) {
MPPasswordType siteType = (MPPasswordType)atoi( str_type ); MPResultType siteType = (MPResultType)atoi( str_type );
if (!mpw_nameForType( siteType )) { if (!mpw_nameForType( siteType )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %s", siteName, str_type ) }; *error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %s", siteName, str_type ) };
return NULL; return NULL;
@ -518,7 +508,8 @@ static MPMarshalledUser *mpw_marshall_read_flat(
return NULL; return NULL;
} }
site->content = mpw_encrypt( masterKey, siteContent, site->algorithm ); site->content = mpw_siteState( masterKey, site->name, site->counter,
MPKeyPurposeAuthentication, NULL, site->type, siteContent, site->algorithm );
} }
else else
// Redacted // Redacted
@ -587,7 +578,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
return NULL; return NULL;
} }
MPAlgorithmVersion algorithm = (MPAlgorithmVersion)value; MPAlgorithmVersion algorithm = (MPAlgorithmVersion)value;
MPPasswordType defaultType = (MPPasswordType)mpw_get_json_int( json_file, "user.default_type", MPPasswordTypeDefault ); MPResultType defaultType = (MPResultType)mpw_get_json_int( json_file, "user.default_type", MPResultTypeDefault );
if (!mpw_nameForType( defaultType )) { if (!mpw_nameForType( defaultType )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) }; *error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) };
return NULL; return NULL;
@ -629,7 +620,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
return NULL; return NULL;
} }
MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)value; MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)value;
MPPasswordType siteType = (MPPasswordType)mpw_get_json_int( json_site.val, "type", user->defaultType ); MPResultType siteType = (MPResultType)mpw_get_json_int( json_site.val, "type", user->defaultType );
if (!mpw_nameForType( siteType )) { if (!mpw_nameForType( siteType )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %u", siteName, siteType ) }; *error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %u", siteName, siteType ) };
return NULL; return NULL;
@ -673,7 +664,8 @@ static MPMarshalledUser *mpw_marshall_read_json(
return NULL; return NULL;
} }
site->content = mpw_encrypt( masterKey, siteContent, site->algorithm ); site->content = mpw_siteState( masterKey, site->name, site->counter,
MPKeyPurposeAuthentication, NULL, site->type, siteContent, site->algorithm );
} }
else else
// Redacted // Redacted
@ -699,10 +691,10 @@ MPMarshalledUser *mpw_marshall_read(
return mpw_marshall_read_flat( in, masterPassword, error ); return mpw_marshall_read_flat( in, masterPassword, error );
case MPMarshallFormatJSON: case MPMarshallFormatJSON:
return mpw_marshall_read_json( in, masterPassword, error ); return mpw_marshall_read_json( in, masterPassword, error );
} default:
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) }; *error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) };
return NULL; return NULL;
}
} }
const MPMarshallFormat mpw_formatWithName( const MPMarshallFormat mpw_formatWithName(

View File

@ -62,7 +62,7 @@ typedef struct MPMarshalledQuestion {
typedef struct MPMarshalledSite { typedef struct MPMarshalledSite {
const char *name; const char *name;
const char *content; const char *content;
MPPasswordType type; MPResultType type;
MPCounterValue counter; MPCounterValue counter;
MPAlgorithmVersion algorithm; MPAlgorithmVersion algorithm;
@ -84,7 +84,7 @@ typedef struct MPMarshalledUser {
bool redacted; bool redacted;
unsigned int avatar; unsigned int avatar;
MPPasswordType defaultType; MPResultType defaultType;
time_t lastUsed; time_t lastUsed;
size_t sites_count; size_t sites_count;
@ -104,7 +104,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 *user, MPMarshalledUser *user,
const char *siteName, const MPPasswordType passwordType, const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion); const char *siteName, const MPResultType resultType, const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion);
MPMarshalledQuestion *mpw_marshal_question( MPMarshalledQuestion *mpw_marshal_question(
MPMarshalledSite *site, const char *keyword); MPMarshalledSite *site, const char *keyword);
bool mpw_marshal_free( bool mpw_marshal_free(

View File

@ -29,28 +29,30 @@
#include "mpw-types.h" #include "mpw-types.h"
#include "mpw-util.h" #include "mpw-util.h"
const MPPasswordType mpw_typeWithName(const char *typeName) { const MPResultType mpw_typeWithName(const char *typeName) {
// Find what password type is represented by the type letter. // Find what password type is represented by the type letter.
if (strlen( typeName ) == 1) { if (strlen( typeName ) == 1) {
if ('x' == typeName[0]) if ('x' == typeName[0])
return MPPasswordTypeGeneratedMaximum; return MPResultTypeTemplateMaximum;
if ('l' == typeName[0]) if ('l' == typeName[0])
return MPPasswordTypeGeneratedLong; return MPResultTypeTemplateLong;
if ('m' == typeName[0]) if ('m' == typeName[0])
return MPPasswordTypeGeneratedMedium; return MPResultTypeTemplateMedium;
if ('b' == typeName[0]) if ('b' == typeName[0])
return MPPasswordTypeGeneratedBasic; return MPResultTypeTemplateBasic;
if ('s' == typeName[0]) if ('s' == typeName[0])
return MPPasswordTypeGeneratedShort; return MPResultTypeTemplateShort;
if ('i' == typeName[0]) if ('i' == typeName[0])
return MPPasswordTypeGeneratedPIN; return MPResultTypeTemplatePIN;
if ('n' == typeName[0]) if ('n' == typeName[0])
return MPPasswordTypeGeneratedName; return MPResultTypeTemplateName;
if ('P' == typeName[0]) if ('P' == typeName[0])
return MPPasswordTypeStoredPersonal; return MPResultTypeStatePersonal;
if ('D' == typeName[0]) if ('D' == typeName[0])
return MPPasswordTypeStoredDevice; return MPResultTypeStateDevice;
if ('k' == typeName[0])
return MPResultTypeDeriveKey;
} }
// 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.
@ -64,71 +66,77 @@ const MPPasswordType mpw_typeWithName(const char *typeName) {
stdTypeName[stdTypeNameSize] = '\0'; stdTypeName[stdTypeNameSize] = '\0';
// Find what password type is represented by the type name. // Find what password type is represented by the type name.
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplateMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPhrase; return MPResultTypeTemplateMaximum;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplateLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedMaximum; return MPResultTypeTemplateLong;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedLong ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplateMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedLong; return MPResultTypeTemplateMedium;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMedium ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplateBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedMedium; return MPResultTypeTemplateBasic;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedBasic ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplateShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedBasic; return MPResultTypeTemplateShort;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedShort ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplatePIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedShort; return MPResultTypeTemplatePIN;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPIN ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplateName ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPIN; return MPResultTypeTemplateName;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedName ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeTemplatePhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedName; return MPResultTypeTemplatePhrase;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0) if (strncmp( mpw_nameForType( MPResultTypeStatePersonal ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPhrase; return MPResultTypeStatePersonal;
if (strncmp( mpw_nameForType( MPResultTypeStateDevice ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeStateDevice;
if (strncmp( mpw_nameForType( MPResultTypeDeriveKey ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeDeriveKey;
dbg( "Not a generated type name: %s\n", stdTypeName ); dbg( "Not a generated type name: %s\n", stdTypeName );
return (MPPasswordType)ERR; return (MPResultType)ERR;
} }
const char *mpw_nameForType(MPPasswordType passwordType) { const char *mpw_nameForType(MPResultType resultType) {
switch (passwordType) { switch (resultType) {
case MPPasswordTypeGeneratedMaximum: case MPResultTypeTemplateMaximum:
return "maximum"; return "maximum";
case MPPasswordTypeGeneratedLong: case MPResultTypeTemplateLong:
return "long"; return "long";
case MPPasswordTypeGeneratedMedium: case MPResultTypeTemplateMedium:
return "medium"; return "medium";
case MPPasswordTypeGeneratedBasic: case MPResultTypeTemplateBasic:
return "basic"; return "basic";
case MPPasswordTypeGeneratedShort: case MPResultTypeTemplateShort:
return "short"; return "short";
case MPPasswordTypeGeneratedPIN: case MPResultTypeTemplatePIN:
return "pin"; return "pin";
case MPPasswordTypeGeneratedName: case MPResultTypeTemplateName:
return "name"; return "name";
case MPPasswordTypeGeneratedPhrase: case MPResultTypeTemplatePhrase:
return "phrase"; return "phrase";
case MPPasswordTypeStoredPersonal: case MPResultTypeStatePersonal:
return "personal"; return "personal";
case MPPasswordTypeStoredDevice: case MPResultTypeStateDevice:
return "device"; return "device";
case MPResultTypeDeriveKey:
return "key";
default: { default: {
dbg( "Unknown password type: %d\n", passwordType ); dbg( "Unknown password type: %d\n", resultType );
return NULL; return NULL;
} }
} }
} }
const char **mpw_templatesForType(MPPasswordType type, size_t *count) { const char **mpw_templatesForType(MPResultType type, size_t *count) {
if (!(type & MPPasswordTypeClassGenerated)) { if (!(type & MPResultTypeClassTemplate)) {
dbg( "Not a generated type: %d\n", type ); dbg( "Not a generated type: %d\n", type );
return NULL; return NULL;
} }
switch (type) { switch (type) {
case MPPasswordTypeGeneratedMaximum: case MPResultTypeTemplateMaximum:
return mpw_alloc_array( count, const char *, return mpw_alloc_array( count, const char *,
"anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" ); "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" );
case MPPasswordTypeGeneratedLong: case MPResultTypeTemplateLong:
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",
@ -137,22 +145,22 @@ const char **mpw_templatesForType(MPPasswordType 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 MPResultTypeTemplateMedium:
return mpw_alloc_array( count, const char *, return mpw_alloc_array( count, const char *,
"CvcnoCvc", "CvcCvcno" ); "CvcnoCvc", "CvcCvcno" );
case MPPasswordTypeGeneratedBasic: case MPResultTypeTemplateBasic:
return mpw_alloc_array( count, const char *, return mpw_alloc_array( count, const char *,
"aaanaaan", "aannaaan", "aaannaaa" ); "aaanaaan", "aannaaan", "aaannaaa" );
case MPPasswordTypeGeneratedShort: case MPResultTypeTemplateShort:
return mpw_alloc_array( count, const char *, return mpw_alloc_array( count, const char *,
"Cvcn" ); "Cvcn" );
case MPPasswordTypeGeneratedPIN: case MPResultTypeTemplatePIN:
return mpw_alloc_array( count, const char *, return mpw_alloc_array( count, const char *,
"nnnn" ); "nnnn" );
case MPPasswordTypeGeneratedName: case MPResultTypeTemplateName:
return mpw_alloc_array( count, const char *, return mpw_alloc_array( count, const char *,
"cvccvcvcv" ); "cvccvcvcv" );
case MPPasswordTypeGeneratedPhrase: case MPResultTypeTemplatePhrase:
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: {
@ -162,7 +170,7 @@ const char **mpw_templatesForType(MPPasswordType type, size_t *count) {
} }
} }
const char *mpw_templateForType(MPPasswordType type, uint8_t seedByte) { const char *mpw_templateForType(MPResultType 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 );

View File

@ -23,11 +23,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#ifdef NS_ENUM //#ifdef NS_ENUM
#define enum(_type, _name) NS_ENUM(_type, _name) //#define enum(_type, _name) NS_ENUM(_type, _name)
#else //#else
#define enum(_type, _name) _type _name; enum #define enum(_type, _name) _type _name; enum
#endif //#endif
//// Types. //// Types.
@ -47,11 +47,13 @@ typedef enum( uint8_t, MPKeyPurpose ) {
}; };
// bit 4 - 9 // bit 4 - 9
typedef enum( uint16_t, MPPasswordTypeClass ) { typedef enum( uint16_t, MPResultTypeClass ) {
/** Generate the password. */ /** Use the site key to generate a password from a template. */
MPPasswordTypeClassGenerated = 1 << 4, MPResultTypeClassTemplate = 1 << 4,
/** Store the password. */ /** Use the site key to encrypt and decrypt a stateful entity. */
MPPasswordTypeClassStored = 1 << 5, MPResultTypeClassState = 1 << 5,
/** Use the site key to derive a site-specific object. */
MPResultTypeClassDerive = 1 << 6,
}; };
// bit 10 - 15 // bit 10 - 15
@ -60,33 +62,38 @@ typedef enum( uint16_t, MPSiteFeature ) {
MPSiteFeatureExportContent = 1 << 10, MPSiteFeatureExportContent = 1 << 10,
/** Never export content. */ /** Never export content. */
MPSiteFeatureDevicePrivate = 1 << 11, MPSiteFeatureDevicePrivate = 1 << 11,
/** Don't use this as the primary authentication result type. */
MPSiteFeatureAlternative = 1 << 12,
}; };
// bit 0-3 | MPPasswordTypeClass | MPSiteFeature // bit 0-3 | MPResultTypeClass | MPSiteFeature
typedef enum( uint32_t, MPPasswordType ) { typedef enum( uint32_t, MPResultType ) {
/** pg^VMAUBk5x3p%HP%i4= */ /** pg^VMAUBk5x3p%HP%i4= */
MPPasswordTypeGeneratedMaximum = 0x0 | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplateMaximum = 0x0 | MPResultTypeClassTemplate | 0x0,
/** BiroYena8:Kixa */ /** BiroYena8:Kixa */
MPPasswordTypeGeneratedLong = 0x1 | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplateLong = 0x1 | MPResultTypeClassTemplate | 0x0,
/** BirSuj0- */ /** BirSuj0- */
MPPasswordTypeGeneratedMedium = 0x2 | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplateMedium = 0x2 | MPResultTypeClassTemplate | 0x0,
/** pO98MoD0 */ /** pO98MoD0 */
MPPasswordTypeGeneratedBasic = 0x4 | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplateBasic = 0x4 | MPResultTypeClassTemplate | 0x0,
/** Bir8 */ /** Bir8 */
MPPasswordTypeGeneratedShort = 0x3 | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplateShort = 0x3 | MPResultTypeClassTemplate | 0x0,
/** 2798 */ /** 2798 */
MPPasswordTypeGeneratedPIN = 0x5 | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplatePIN = 0x5 | MPResultTypeClassTemplate | 0x0,
/** birsujano */ /** birsujano */
MPPasswordTypeGeneratedName = 0xE | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplateName = 0xE | MPResultTypeClassTemplate | 0x0,
/** bir yennoquce fefi */ /** bir yennoquce fefi */
MPPasswordTypeGeneratedPhrase = 0xF | MPPasswordTypeClassGenerated | 0x0, MPResultTypeTemplatePhrase = 0xF | MPResultTypeClassTemplate | 0x0,
/** Custom saved password. */ /** Custom saved password. */
MPPasswordTypeStoredPersonal = 0x0 | MPPasswordTypeClassStored | MPSiteFeatureExportContent, MPResultTypeStatePersonal = 0x0 | MPResultTypeClassState | MPSiteFeatureExportContent,
/** Custom saved password that should not be exported from the device. */ /** Custom saved password that should not be exported from the device. */
MPPasswordTypeStoredDevice = 0x1 | MPPasswordTypeClassStored | MPSiteFeatureDevicePrivate, MPResultTypeStateDevice = 0x1 | MPResultTypeClassState | MPSiteFeatureDevicePrivate,
MPPasswordTypeDefault = MPPasswordTypeGeneratedLong, /** Derive a unique binary key. */
MPResultTypeDeriveKey = 0x0 | MPResultTypeClassDerive | MPSiteFeatureAlternative,
MPResultTypeDefault = MPResultTypeTemplateLong,
}; };
typedef enum ( uint32_t, MPCounterValue ) { typedef enum ( uint32_t, MPCounterValue ) {
@ -118,11 +125,11 @@ const char *mpw_scopeForPurpose(MPKeyPurpose purpose);
/** /**
* @return The password type represented by the given name. * @return The password type represented by the given name.
*/ */
const MPPasswordType mpw_typeWithName(const char *typeName); const MPResultType mpw_typeWithName(const char *typeName);
/** /**
* @return The standard name for the given password type. * @return The standard name for the given password type.
*/ */
const char *mpw_nameForType(MPPasswordType passwordType); const char *mpw_nameForType(MPResultType resultType);
/** /**
* @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.
@ -130,12 +137,12 @@ const char *mpw_nameForType(MPPasswordType passwordType);
* 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(MPPasswordType type, size_t *count); const char **mpw_templatesForType(MPResultType 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(MPPasswordType type, uint8_t seedByte); const char *mpw_templateForType(MPResultType 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

@ -18,6 +18,7 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#if MPW_COLOR #if MPW_COLOR
#include <unistd.h> #include <unistd.h>
@ -32,6 +33,7 @@
#include "sodium.h" #include "sodium.h"
#ifdef SODIUM_LIBRARY_MINIMAL #ifdef SODIUM_LIBRARY_MINIMAL
#include "crypto_stream_aes128ctr.h" #include "crypto_stream_aes128ctr.h"
#include "crypto_kdf_blake2b.h"
#endif #endif
#endif #endif
@ -122,7 +124,7 @@ bool mpw_free_string(const char *string) {
return string && mpw_free( string, strlen( string ) ); return string && mpw_free( string, strlen( string ) );
} }
uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize, uint8_t const *mpw_kdf_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
uint64_t N, uint32_t r, uint32_t p) { uint64_t N, uint32_t r, uint32_t p) {
if (!secret || !salt) if (!secret || !salt)
@ -149,7 +151,49 @@ uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_
return key; return key;
} }
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *message, const size_t messageSize) { uint8_t const *mpw_kdf_blake2b(const size_t subkeySize, const uint8_t *key, const size_t keySize,
const uint8_t *context, const size_t contextSize, const uint64_t id, const char *personal) {
if (!key || !keySize || !subkeySize) {
errno = EINVAL;
return NULL;
}
uint8_t *subkey = malloc( subkeySize );
if (!subkey)
return NULL;
#if HAS_SODIUM
if (personal && strlen( personal ) > crypto_generichash_blake2b_PERSONALBYTES) {
errno = EINVAL;
free( subkey );
return NULL;
}
uint8_t saltBuf[crypto_generichash_blake2b_SALTBYTES];
bzero( saltBuf, sizeof saltBuf );
if (id) {
uint64_t id_n = htonll( id );
memcpy( saltBuf, &id_n, sizeof id_n );
}
uint8_t personalBuf[crypto_generichash_blake2b_PERSONALBYTES];
bzero( personalBuf, sizeof saltBuf );
if (personal && strlen( personal ))
memcpy( personalBuf, personal, strlen( personal ) );
if (crypto_generichash_blake2b_salt_personal( subkey, subkeySize, context, contextSize, key, keySize, saltBuf, personalBuf ) != 0) {
mpw_free( subkey, subkeySize );
return NULL;
}
#else
#error No crypto support for mpw_scrypt.
#endif
return subkey;
}
uint8_t const *mpw_hash_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *message, const size_t messageSize) {
if (!key || !keySize || !message || !messageSize) if (!key || !keySize || !message || !messageSize)
return NULL; return NULL;
@ -330,7 +374,8 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
}; };
const uint8_t *identiconSeed = mpw_hmac_sha256( (const uint8_t *)masterPassword, strlen( masterPassword ), (const uint8_t *)fullName, const uint8_t *identiconSeed = mpw_hash_hmac_sha256( (const uint8_t *)masterPassword, strlen( masterPassword ),
(const uint8_t *)fullName,
strlen( fullName ) ); strlen( fullName ) );
if (!identiconSeed) if (!identiconSeed)
return NULL; return NULL;

View File

@ -141,12 +141,17 @@ bool mpw_free_string(
/** Derive a key from the given secret and salt using the scrypt KDF. /** Derive a key from the given secret and salt using the scrypt KDF.
* @return A new keySize allocated buffer containing the key. */ * @return A new keySize allocated buffer containing the key. */
uint8_t const *mpw_scrypt( uint8_t const *mpw_kdf_scrypt(
const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize, const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
uint64_t N, uint32_t r, uint32_t p); uint64_t N, uint32_t r, uint32_t p);
/** Derive a subkey from the given key.
* @return A new keySize allocated buffer containing the key. */
uint8_t const *mpw_kdf_blake2b(
const size_t subkeySize, const uint8_t *key, const size_t keySize,
const uint8_t *context, const size_t contextSize, const uint64_t id, const char *personal);
/** Calculate the MAC for the given message with the given key using SHA256-HMAC. /** Calculate the MAC for the given message with the given key using SHA256-HMAC.
* @return A new 32-byte allocated buffer containing the MAC. */ * @return A new 32-byte allocated buffer containing the MAC. */
uint8_t const *mpw_hmac_sha256( uint8_t const *mpw_hash_hmac_sha256(
const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize); const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize);
/** Encrypt a plainBuf with the given key using AES-128-CBC. /** Encrypt a plainBuf with the given key using AES-128-CBC.
* @return A new bufSize allocated buffer containing the cipherBuf. */ * @return A new bufSize allocated buffer containing the cipherBuf. */

View File

@ -7,7 +7,7 @@
<keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID> <keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID>
<siteName>masterpasswordapp.com</siteName> <siteName>masterpasswordapp.com</siteName>
<siteCounter>1</siteCounter> <siteCounter>1</siteCounter>
<passwordType>GeneratedLong</passwordType> <resultType>GeneratedLong</resultType>
<keyPurpose>Authentication</keyPurpose> <keyPurpose>Authentication</keyPurpose>
<result><!-- abstract --></result> <result><!-- abstract --></result>
</case> </case>
@ -33,12 +33,12 @@
</case> </case>
<case id="v3_loginName" parent="v3"> <case id="v3_loginName" parent="v3">
<keyPurpose>Identification</keyPurpose> <keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>wohzaqage</result> <result>wohzaqage</result>
</case> </case>
<case id="v3_securityAnswer" parent="v3"> <case id="v3_securityAnswer" parent="v3">
<keyPurpose>Recovery</keyPurpose> <keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -46,31 +46,31 @@
<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">
<passwordType>GeneratedMaximum</passwordType> <resultType>GeneratedMaximum</resultType>
<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">
<passwordType>GeneratedMedium</passwordType> <resultType>GeneratedMedium</resultType>
<result>Jej2$Quv</result> <result>Jej2$Quv</result>
</case> </case>
<case id="v3_type_basic" parent="v3"> <case id="v3_type_basic" parent="v3">
<passwordType>GeneratedBasic</passwordType> <resultType>GeneratedBasic</resultType>
<result>WAo2xIg6</result> <result>WAo2xIg6</result>
</case> </case>
<case id="v3_type_short" parent="v3"> <case id="v3_type_short" parent="v3">
<passwordType>GeneratedShort</passwordType> <resultType>GeneratedShort</resultType>
<result>Jej2</result> <result>Jej2</result>
</case> </case>
<case id="v3_type_pin" parent="v3"> <case id="v3_type_pin" parent="v3">
<passwordType>GeneratedPIN</passwordType> <resultType>GeneratedPIN</resultType>
<result>7662</result> <result>7662</result>
</case> </case>
<case id="v3_type_name" parent="v3"> <case id="v3_type_name" parent="v3">
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>jejraquvo</result> <result>jejraquvo</result>
</case> </case>
<case id="v3_type_phrase" parent="v3"> <case id="v3_type_phrase" parent="v3">
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -99,12 +99,12 @@
</case> </case>
<case id="v2_loginName" parent="v2"> <case id="v2_loginName" parent="v2">
<keyPurpose>Identification</keyPurpose> <keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>wohzaqage</result> <result>wohzaqage</result>
</case> </case>
<case id="v2_securityAnswer" parent="v2"> <case id="v2_securityAnswer" parent="v2">
<keyPurpose>Recovery</keyPurpose> <keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -112,31 +112,31 @@
<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">
<passwordType>GeneratedMaximum</passwordType> <resultType>GeneratedMaximum</resultType>
<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">
<passwordType>GeneratedMedium</passwordType> <resultType>GeneratedMedium</resultType>
<result>Jej2$Quv</result> <result>Jej2$Quv</result>
</case> </case>
<case id="v2_type_basic" parent="v2"> <case id="v2_type_basic" parent="v2">
<passwordType>GeneratedBasic</passwordType> <resultType>GeneratedBasic</resultType>
<result>WAo2xIg6</result> <result>WAo2xIg6</result>
</case> </case>
<case id="v2_type_short" parent="v2"> <case id="v2_type_short" parent="v2">
<passwordType>GeneratedShort</passwordType> <resultType>GeneratedShort</resultType>
<result>Jej2</result> <result>Jej2</result>
</case> </case>
<case id="v2_type_pin" parent="v2"> <case id="v2_type_pin" parent="v2">
<passwordType>GeneratedPIN</passwordType> <resultType>GeneratedPIN</resultType>
<result>7662</result> <result>7662</result>
</case> </case>
<case id="v2_type_name" parent="v2"> <case id="v2_type_name" parent="v2">
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>jejraquvo</result> <result>jejraquvo</result>
</case> </case>
<case id="v2_type_phrase" parent="v2"> <case id="v2_type_phrase" parent="v2">
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -165,12 +165,12 @@
</case> </case>
<case id="v1_loginName" parent="v1"> <case id="v1_loginName" parent="v1">
<keyPurpose>Identification</keyPurpose> <keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>wohzaqage</result> <result>wohzaqage</result>
</case> </case>
<case id="v1_securityAnswer" parent="v1"> <case id="v1_securityAnswer" parent="v1">
<keyPurpose>Recovery</keyPurpose> <keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -178,31 +178,31 @@
<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">
<passwordType>GeneratedMaximum</passwordType> <resultType>GeneratedMaximum</resultType>
<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">
<passwordType>GeneratedMedium</passwordType> <resultType>GeneratedMedium</resultType>
<result>Jej2$Quv</result> <result>Jej2$Quv</result>
</case> </case>
<case id="v1_type_basic" parent="v1"> <case id="v1_type_basic" parent="v1">
<passwordType>GeneratedBasic</passwordType> <resultType>GeneratedBasic</resultType>
<result>WAo2xIg6</result> <result>WAo2xIg6</result>
</case> </case>
<case id="v1_type_short" parent="v1"> <case id="v1_type_short" parent="v1">
<passwordType>GeneratedShort</passwordType> <resultType>GeneratedShort</resultType>
<result>Jej2</result> <result>Jej2</result>
</case> </case>
<case id="v1_type_pin" parent="v1"> <case id="v1_type_pin" parent="v1">
<passwordType>GeneratedPIN</passwordType> <resultType>GeneratedPIN</resultType>
<result>7662</result> <result>7662</result>
</case> </case>
<case id="v1_type_name" parent="v1"> <case id="v1_type_name" parent="v1">
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>jejraquvo</result> <result>jejraquvo</result>
</case> </case>
<case id="v1_type_phrase" parent="v1"> <case id="v1_type_phrase" parent="v1">
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -231,12 +231,12 @@
</case> </case>
<case id="v0_loginName" parent="v0"> <case id="v0_loginName" parent="v0">
<keyPurpose>Identification</keyPurpose> <keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>lozwajave</result> <result>lozwajave</result>
</case> </case>
<case id="v0_securityAnswer" parent="v0"> <case id="v0_securityAnswer" parent="v0">
<keyPurpose>Recovery</keyPurpose> <keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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">
@ -244,31 +244,31 @@
<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">
<passwordType>GeneratedMaximum</passwordType> <resultType>GeneratedMaximum</resultType>
<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">
<passwordType>GeneratedMedium</passwordType> <resultType>GeneratedMedium</resultType>
<result>Fej7]Jug</result> <result>Fej7]Jug</result>
</case> </case>
<case id="v0_type_basic" parent="v0"> <case id="v0_type_basic" parent="v0">
<passwordType>GeneratedBasic</passwordType> <resultType>GeneratedBasic</resultType>
<result>wvH7irC1</result> <result>wvH7irC1</result>
</case> </case>
<case id="v0_type_short" parent="v0"> <case id="v0_type_short" parent="v0">
<passwordType>GeneratedShort</passwordType> <resultType>GeneratedShort</resultType>
<result>Fej7</result> <result>Fej7</result>
</case> </case>
<case id="v0_type_pin" parent="v0"> <case id="v0_type_pin" parent="v0">
<passwordType>GeneratedPIN</passwordType> <resultType>GeneratedPIN</resultType>
<result>2117</result> <result>2117</result>
</case> </case>
<case id="v0_type_name" parent="v0"> <case id="v0_type_name" parent="v0">
<passwordType>GeneratedName</passwordType> <resultType>GeneratedName</resultType>
<result>fejrajugo</result> <result>fejrajugo</result>
</case> </case>
<case id="v0_type_phrase" parent="v0"> <case id="v0_type_phrase" parent="v0">
<passwordType>GeneratedPhrase</passwordType> <resultType>GeneratedPhrase</resultType>
<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

@ -50,7 +50,7 @@ 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 MPCounterValue siteCounter = MPCounterValueDefault; const MPCounterValue siteCounter = MPCounterValueDefault;
const MPPasswordType passwordType = MPPasswordTypeDefault; const MPResultType resultType = MPResultTypeDefault;
const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication; const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
const char *keyContext = NULL; const char *keyContext = NULL;
struct timeval startTime; struct timeval startTime;
@ -69,7 +69,7 @@ int main(int argc, char *const argv[]) {
} }
mpw_getTime( &startTime ); mpw_getTime( &startTime );
for (int i = 1; i <= iterations; ++i) { for (int i = 1; i <= iterations; ++i) {
free( (void *)mpw_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, 128 ) ); free( (void *)mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, 128 ) );
if (modff(100.f * i / iterations, &percent) == 0) if (modff(100.f * i / iterations, &percent) == 0)
fprintf( stderr, "\rhmac-sha-256: iteration %d / %d (%.0f%%)..", i, iterations, percent ); fprintf( stderr, "\rhmac-sha-256: iteration %d / %d (%.0f%%)..", i, iterations, percent );
@ -113,12 +113,9 @@ int main(int argc, char *const argv[]) {
break; break;
} }
MPSiteKey siteKey = mpw_siteKey( free( (void *)mpw_siteResult(
masterKey, siteName, siteCounter, keyPurpose, keyContext, MPAlgorithmVersionCurrent ); masterKey, siteName, siteCounter, keyPurpose, keyContext, resultType, NULL, MPAlgorithmVersionCurrent ) );
free( (void *)mpw_sitePassword(
siteKey, passwordType, MPAlgorithmVersionCurrent ) );
free( (void *)masterKey ); free( (void *)masterKey );
free( (void *)siteKey );
if (modff(100.f * i / iterations, &percent) == 0) if (modff(100.f * i / iterations, &percent) == 0)
fprintf( stderr, "\rmpw: iteration %d / %d (%.0f%%)..", i, iterations, percent ); fprintf( stderr, "\rmpw: iteration %d / %d (%.0f%%)..", i, iterations, percent );

View File

@ -47,7 +47,8 @@ static void usage() {
" 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" " p, phrase | 20 character sentence.\n"
" P, personal | saved personal password (see -s).\n\n" ); " K, key | encryption key (set key size -s bits).\n"
" P, personal | saved personal password (save with -s pw).\n\n" );
inf( "" inf( ""
" -c counter The value of the counter.\n" " -c counter The value of the counter.\n"
" Defaults to 1.\n\n" ); " Defaults to 1.\n\n" );
@ -56,7 +57,8 @@ static void usage() {
" Defaults to %s in env or %d.\n\n", " Defaults to %s in env or %d.\n\n",
MPAlgorithmVersionFirst, MPAlgorithmVersionLast, MP_ENV_algorithm, MPAlgorithmVersionCurrent ); MPAlgorithmVersionFirst, MPAlgorithmVersionLast, MP_ENV_algorithm, MPAlgorithmVersionCurrent );
inf( "" inf( ""
" -s value The value to save for -t P or -p i.\n\n" ); " -s value The value to save for -t P or -p i.\n"
" The size of they key to generate for -t K, in bits (eg. 256).\n\n" );
inf( "" inf( ""
" -p purpose The purpose of the generated token.\n" " -p purpose The purpose of the generated token.\n"
" Defaults to 'auth'.\n" " Defaults to 'auth'.\n"
@ -150,9 +152,9 @@ static char *mpw_path(const char *prefix, const char *extension) {
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, *saveValue = NULL, *keyContext = NULL; const char *fullName = NULL, *masterPassword = NULL, *siteName = NULL, *resultParam = NULL, *keyContext = NULL;
MPCounterValue siteCounter = MPCounterValueDefault; MPCounterValue siteCounter = MPCounterValueDefault;
MPPasswordType passwordType = MPPasswordTypeDefault; MPResultType resultType = MPResultTypeDefault;
MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication; MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent; MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
MPMarshallFormat sitesFormat = MPMarshallFormatDefault; MPMarshallFormat sitesFormat = MPMarshallFormatDefault;
@ -160,13 +162,13 @@ int main(int argc, char *const argv[]) {
// Read the environment. // Read the environment.
const char *fullNameArg = NULL, *masterPasswordArg = NULL, *siteNameArg = NULL; const char *fullNameArg = NULL, *masterPasswordArg = NULL, *siteNameArg = NULL;
const char *passwordTypeArg = NULL, *siteCounterArg = NULL, *algorithmVersionArg = NULL, *saveValueArg = NULL; const char *resultTypeArg = NULL, *resultParamArg = NULL, *siteCounterArg = NULL, *algorithmVersionArg = NULL;
const char *keyPurposeArg = NULL, *keyContextArg = NULL, *sitesFormatArg = NULL, *sitesRedactedArg = NULL; const char *keyPurposeArg = NULL, *keyContextArg = NULL, *sitesFormatArg = NULL, *sitesRedactedArg = NULL;
fullNameArg = mpw_getenv( MP_ENV_fullName ); fullNameArg = mpw_getenv( MP_ENV_fullName );
algorithmVersionArg = mpw_getenv( MP_ENV_algorithm ); algorithmVersionArg = mpw_getenv( MP_ENV_algorithm );
// Read the command-line options. // Read the command-line options.
for (int opt; (opt = getopt( argc, argv, "u:U:P:t:c:a:s:p:C:f:F:R:vqh" )) != EOF;) for (int opt; (opt = getopt( argc, argv, "u:U:M:t:P:c:a:s:p:C:f:F:R:vqh" )) != EOF;)
switch (opt) { switch (opt) {
case 'u': case 'u':
fullNameArg = optarg && strlen( optarg )? strdup( optarg ): NULL; fullNameArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
@ -176,12 +178,15 @@ int main(int argc, char *const argv[]) {
fullNameArg = optarg && strlen( optarg )? strdup( optarg ): NULL; fullNameArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
allowPasswordUpdate = true; allowPasswordUpdate = true;
break; break;
case 'P': case 'M':
// Passing your master password via the command-line is insecure. Testing purposes only. // Passing your master password via the command-line is insecure. Testing purposes only.
masterPasswordArg = optarg && strlen( optarg )? strdup( optarg ): NULL; masterPasswordArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break; break;
case 't': case 't':
passwordTypeArg = optarg && strlen( optarg )? strdup( optarg ): NULL; resultTypeArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break;
case 'P':
resultParamArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break; break;
case 'c': case 'c':
siteCounterArg = optarg && strlen( optarg )? strdup( optarg ): NULL; siteCounterArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
@ -189,9 +194,6 @@ int main(int argc, char *const argv[]) {
case 'a': case 'a':
algorithmVersionArg = optarg && strlen( optarg )? strdup( optarg ): NULL; algorithmVersionArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break; break;
case 's':
saveValueArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break;
case 'p': case 'p':
keyPurposeArg = optarg && strlen( optarg )? strdup( optarg ): NULL; keyPurposeArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break; break;
@ -342,7 +344,7 @@ int main(int argc, char *const argv[]) {
fullName = strdup( user->fullName ); fullName = strdup( user->fullName );
masterPassword = strdup( user->masterPassword ); masterPassword = strdup( user->masterPassword );
algorithmVersion = user->algorithm; algorithmVersion = user->algorithm;
passwordType = user->defaultType; resultType = user->defaultType;
sitesRedacted = user->redacted; sitesRedacted = user->redacted;
if (!sitesRedacted && !sitesRedactedArg) if (!sitesRedacted && !sitesRedactedArg)
@ -355,8 +357,8 @@ int main(int argc, char *const argv[]) {
continue; continue;
} }
mpw_free_string( saveValue ); mpw_free_string( resultParam );
passwordType = site->type; resultType = site->type;
siteCounter = site->counter; siteCounter = site->counter;
algorithmVersion = site->algorithm; algorithmVersion = site->algorithm;
break; break;
@ -383,10 +385,6 @@ int main(int argc, char *const argv[]) {
} }
algorithmVersion = (MPAlgorithmVersion)algorithmVersionInt; algorithmVersion = (MPAlgorithmVersion)algorithmVersionInt;
} }
if (saveValueArg) {
mpw_free_string( saveValue );
saveValue = strdup( saveValueArg );
}
if (keyPurposeArg) { if (keyPurposeArg) {
keyPurpose = mpw_purposeWithName( keyPurposeArg ); keyPurpose = mpw_purposeWithName( keyPurposeArg );
if (ERR == (int)keyPurpose) { if (ERR == (int)keyPurpose) {
@ -399,23 +397,27 @@ int main(int argc, char *const argv[]) {
case MPKeyPurposeAuthentication: case MPKeyPurposeAuthentication:
break; break;
case MPKeyPurposeIdentification: { case MPKeyPurposeIdentification: {
passwordType = MPPasswordTypeGeneratedName; resultType = MPResultTypeTemplateName;
purposeResult = "login"; purposeResult = "login";
break; break;
} }
case MPKeyPurposeRecovery: { case MPKeyPurposeRecovery: {
passwordType = MPPasswordTypeGeneratedPhrase; resultType = MPResultTypeTemplatePhrase;
purposeResult = "answer"; purposeResult = "answer";
break; break;
} }
} }
if (passwordTypeArg) { if (resultTypeArg) {
passwordType = mpw_typeWithName( passwordTypeArg ); resultType = mpw_typeWithName( resultTypeArg );
if (ERR == (int)passwordType) { if (ERR == (int)resultType) {
ftl( "Invalid type: %s\n", passwordTypeArg ); ftl( "Invalid type: %s\n", resultTypeArg );
return EX_USAGE; return EX_USAGE;
} }
} }
if (resultParamArg) {
mpw_free_string( resultParam );
resultParam = strdup( resultParamArg );
}
if (keyContextArg) { if (keyContextArg) {
mpw_free_string( keyContext ); mpw_free_string( keyContext );
keyContext = strdup( keyContextArg ); keyContext = strdup( keyContextArg );
@ -423,10 +425,10 @@ int main(int argc, char *const argv[]) {
mpw_free_string( fullNameArg ); mpw_free_string( fullNameArg );
mpw_free_string( masterPasswordArg ); mpw_free_string( masterPasswordArg );
mpw_free_string( siteNameArg ); mpw_free_string( siteNameArg );
mpw_free_string( passwordTypeArg ); mpw_free_string( resultTypeArg );
mpw_free_string( resultParamArg );
mpw_free_string( siteCounterArg ); mpw_free_string( siteCounterArg );
mpw_free_string( algorithmVersionArg ); mpw_free_string( algorithmVersionArg );
mpw_free_string( saveValueArg );
mpw_free_string( keyPurposeArg ); mpw_free_string( keyPurposeArg );
mpw_free_string( keyContextArg ); mpw_free_string( keyContextArg );
mpw_free_string( sitesFormatArg ); mpw_free_string( sitesFormatArg );
@ -444,10 +446,10 @@ int main(int argc, char *const argv[]) {
dbg( "sitesPath : %s\n", sitesPath ); dbg( "sitesPath : %s\n", sitesPath );
dbg( "siteName : %s\n", siteName ); dbg( "siteName : %s\n", siteName );
dbg( "siteCounter : %u\n", siteCounter ); dbg( "siteCounter : %u\n", siteCounter );
dbg( "saveValue : %s\n", saveValue ); dbg( "resultType : %s (%u)\n", mpw_nameForType( resultType ), resultType );
dbg( "resultParam : %s\n", resultParam );
dbg( "keyPurpose : %s (%u)\n", mpw_nameForPurpose( keyPurpose ), keyPurpose ); dbg( "keyPurpose : %s (%u)\n", mpw_nameForPurpose( keyPurpose ), keyPurpose );
dbg( "keyContext : %s\n", keyContext ); dbg( "keyContext : %s\n", keyContext );
dbg( "passwordType : %s (%u)\n", mpw_nameForType( passwordType ), passwordType );
dbg( "algorithmVersion : %u\n", algorithmVersion ); dbg( "algorithmVersion : %u\n", algorithmVersion );
dbg( "-----------------\n\n" ); dbg( "-----------------\n\n" );
inf( "%s's %s for %s:\n[ %s ]: ", fullName, purposeResult, siteName, identicon ); inf( "%s's %s for %s:\n[ %s ]: ", fullName, purposeResult, siteName, identicon );
@ -469,71 +471,57 @@ int main(int argc, char *const argv[]) {
if (keyPurpose == MPKeyPurposeIdentification && site && !site->loginGenerated && site->loginName) if (keyPurpose == MPKeyPurposeIdentification && site && !site->loginGenerated && site->loginName)
fprintf( stdout, "%s\n", site->loginName ); fprintf( stdout, "%s\n", site->loginName );
else if (passwordType & MPPasswordTypeClassGenerated) { else if (resultParam && site && resultType & MPResultTypeClassState) {
MPSiteKey siteKey = mpw_siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext, algorithmVersion );
const char *sitePassword = mpw_sitePassword( siteKey, passwordType, algorithmVersion );
mpw_free( siteKey, MPSiteKeySize );
if (!sitePassword) {
ftl( "Couldn't derive site password.\n" );
mpw_free( masterKey, MPMasterKeySize );
return EX_SOFTWARE;
}
fprintf( stdout, "%s\n", sitePassword );
mpw_free_string( sitePassword );
}
else {
const char *content = NULL;
if (saveValue) {
content = strdup( saveValue );
if (site) {
// TODO: Doesn't save content for newly created sites.
mpw_free_string( site->content ); mpw_free_string( site->content );
if (!(site->content = mpw_encrypt( masterKey, saveValue, algorithmVersion ))) if (!(site->content = mpw_siteState( masterKey, siteName, siteCounter,
err( "Couldn't encrypt site content.\n" ); keyPurpose, keyContext, resultType, resultParam, algorithmVersion ))) {
} ftl( "Couldn't encrypt site content.\n" );
}
else if (site && site->content) {
content = mpw_decrypt( masterKey, site->content, algorithmVersion );
if (!content) {
ftl( "Couldn't decrypt site content.\n" );
mpw_free( masterKey, MPMasterKeySize ); mpw_free( masterKey, MPMasterKeySize );
return EX_SOFTWARE; return EX_SOFTWARE;
} }
inf( "saved.\n" );
}
else {
if (!resultParam && site && site->content && resultType & MPResultTypeClassState)
resultParam = strdup( site->content );
const char *siteResult = mpw_siteResult( masterKey, siteName, siteCounter,
keyPurpose, keyContext, resultType, resultParam, algorithmVersion );
if (!siteResult) {
ftl( "Couldn't generate site result.\n" );
mpw_free( masterKey, MPMasterKeySize );
return EX_SOFTWARE;
} }
fprintf( stdout, "%s\n", content ); fprintf( stdout, "%s\n", siteResult );
mpw_free_string( content ); mpw_free_string( siteResult );
} }
if (site && site->url) if (site && site->url)
inf( "See: %s\n", site->url ); inf( "See: %s\n", site->url );
mpw_free( masterKey, MPMasterKeySize ); mpw_free( masterKey, MPMasterKeySize );
mpw_free_string( siteName ); mpw_free_string( siteName );
mpw_free_string( saveValue ); mpw_free_string( resultParam );
mpw_free_string( keyContext ); mpw_free_string( keyContext );
// Update the mpsites file. // Update the mpsites file.
if (user) { if (user) {
// TODO: Move this up above the summary and replace the mpw lvars by user/site accessors. // TODO: Move this up above the summary and replace the mpw lvars by user/site accessors.
if (keyPurpose == MPKeyPurposeAuthentication) { if (keyPurpose == MPKeyPurposeAuthentication && !(resultType & MPSiteFeatureAlternative)) {
if (!site) if (!site)
site = mpw_marshall_site( user, siteName, passwordType, siteCounter, algorithmVersion ); site = mpw_marshall_site( user, siteName, resultType, siteCounter, algorithmVersion );
else { else {
site->type = passwordType; site->type = resultType;
site->counter = siteCounter; site->counter = siteCounter;
site->algorithm = algorithmVersion; site->algorithm = algorithmVersion;
} }
} }
else if (keyPurpose == MPKeyPurposeIdentification && site) { else if (keyPurpose == MPKeyPurposeIdentification && site) {
// TODO: We're not persisting the passwordType of the generated login // TODO: We're not persisting the resultType of the generated login
if (passwordType & MPPasswordTypeClassGenerated) if (resultType & MPResultTypeClassTemplate)
site->loginGenerated = true; site->loginGenerated = true;
} }
else if (keyPurpose == MPKeyPurposeRecovery && site && keyContext) { else if (keyPurpose == MPKeyPurposeRecovery && site && keyContext) {
// TODO: We're not persisting the passwordType of the recovery question // TODO: We're not persisting the resultType of the recovery question
MPMarshalledQuestion *question = NULL; MPMarshalledQuestion *question = NULL;
for (size_t q = 0; q < site->questions_count; ++q) { for (size_t q = 0; q < site->questions_count; ++q) {
question = &site->questions[q]; question = &site->questions[q];

View File

@ -30,13 +30,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" );
MPCounterValue siteCounter = (MPCounterValue)mpw_xmlTestCaseInteger( testCase, "siteCounter" ); MPCounterValue siteCounter = (MPCounterValue)mpw_xmlTestCaseInteger( testCase, "siteCounter" );
xmlChar *passwordTypeString = mpw_xmlTestCaseString( testCase, "passwordType" ); xmlChar *resultTypeString = mpw_xmlTestCaseString( testCase, "resultType" );
xmlChar *keyPurposeString = mpw_xmlTestCaseString( testCase, "keyPurpose" ); xmlChar *keyPurposeString = mpw_xmlTestCaseString( testCase, "keyPurpose" );
xmlChar *keyContext = mpw_xmlTestCaseString( testCase, "keyContext" ); xmlChar *keyContext = mpw_xmlTestCaseString( testCase, "keyContext" );
xmlChar *result = mpw_xmlTestCaseString( testCase, "result" ); xmlChar *result = mpw_xmlTestCaseString( testCase, "result" );
MPPasswordType siteType = mpw_typeWithName( (char *)passwordTypeString ); MPResultType resultType = mpw_typeWithName( (char *)resultTypeString );
MPKeyPurpose siteVariant = mpw_purposeWithName( (char *)keyPurposeString ); MPKeyPurpose keyPurpose = mpw_purposeWithName( (char *)keyPurposeString );
// Run the test case. // Run the test case.
fprintf( stdout, "test case %s... ", id ); fprintf( stdout, "test case %s... ", id );
@ -54,12 +54,9 @@ int main(int argc, char *const argv[]) {
} }
// 2. calculate the site password. // 2. calculate the site password.
MPSiteKey siteKey = mpw_siteKey( const char *sitePassword = mpw_siteResult(
masterKey, (char *)siteName, siteCounter, siteVariant, (char *)keyContext, algorithm ); masterKey, (char *)siteName, siteCounter, keyPurpose, (char *)keyContext, resultType, NULL, algorithm );
const char *sitePassword = mpw_sitePassword(
siteKey, siteType, algorithm );
mpw_free( masterKey, MPMasterKeySize ); mpw_free( masterKey, MPMasterKeySize );
mpw_free( siteKey, MPSiteKeySize );
if (!sitePassword) { if (!sitePassword) {
ftl( "Couldn't derive site password.\n" ); ftl( "Couldn't derive site password.\n" );
continue; continue;
@ -81,7 +78,7 @@ int main(int argc, char *const argv[]) {
xmlFree( masterPassword ); xmlFree( masterPassword );
xmlFree( keyID ); xmlFree( keyID );
xmlFree( siteName ); xmlFree( siteName );
xmlFree( passwordTypeString ); xmlFree( resultTypeString );
xmlFree( keyPurposeString ); xmlFree( keyPurposeString );
xmlFree( keyContext ); xmlFree( keyContext );
xmlFree( result ); xmlFree( result );

View File

@ -5,7 +5,6 @@ cd "${BASH_SOURCE%/*}"
tag=$(git describe --match '*-cli*') tag=$(git describe --match '*-cli*')
commit=$(git describe --long --dirty --match '*-cli*') commit=$(git describe --long --dirty --match '*-cli*')
[[ $commit != *-dirty ]] || { echo >&2 "Tree is dirty, first commit any changes."; exit 1; } [[ $commit != *-dirty ]] || { echo >&2 "Tree is dirty, first commit any changes."; exit 1; }
git show --show-signature --pretty=format:%H --quiet "$tag" > VERSION
mpwArchive=mpw-$commit.tar.gz mpwArchive=mpw-$commit.tar.gz
[[ -e $mpwArchive ]] && echo >&2 "WARNING: $mpwArchive already exists. Will overwrite." [[ -e $mpwArchive ]] && echo >&2 "WARNING: $mpwArchive already exists. Will overwrite."
@ -15,6 +14,7 @@ echo "Cleaning .."
( git clean -ffdx . && cd core && git clean -ffdx . ) ( git clean -ffdx . && cd core && git clean -ffdx . )
echo "Creating archive $mpwArchive .." echo "Creating archive $mpwArchive .."
git show --show-signature --pretty=format:%H --quiet "$tag" > VERSION
git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive" git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive"
echo "Creating archive signature $mpwArchive.sig .." echo "Creating archive signature $mpwArchive.sig .."