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

View File

@ -50,17 +50,18 @@ MPSiteKey mpw_siteKey(
/** Encode a password for the site from the given site key.
* @return A newly allocated string or NULL if an error occurred. */
const char *mpw_sitePassword(
MPSiteKey siteKey, const MPPasswordType passwordType, const MPAlgorithmVersion algorithmVersion);
const char *mpw_siteResult(
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.
* @return The newly allocated cipherText of the secret token encrypted by the masterKey. */
const char *mpw_encrypt(
MPMasterKey masterKey, const char *plainText, const MPAlgorithmVersion algorithmVersion);
/** Perform symmetric decryption on a secret token's cipherText.
* @return The newly allocated plainText of the secret token decrypted by the masterKey. */
const char *mpw_decrypt(
MPMasterKey masterKey, const char *cipherText, const MPAlgorithmVersion algorithmVersion);
const char *mpw_siteState(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext,
const MPResultType resultType, const char *state,
const MPAlgorithmVersion algorithmVersion);
#endif // _MPW_ALGORITHM_H

View File

@ -29,7 +29,7 @@
#define MP_p 2U
// 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;
const char **templates = mpw_templatesForType( type, &count );
@ -70,7 +70,7 @@ static MPMasterKey mpw_masterKey_v0(
// Calculate the master key.
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 );
if (!masterKey) {
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",
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 );
if (!siteKey) {
err( "Could not allocate site key: %s\n", strerror( errno ) );
err( "Could not derive site key: %s\n", strerror( errno ) );
return NULL;
}
trc( " => siteKey.id: %s\n", mpw_id_buf( siteKey, MPSiteKeySize ) );
@ -124,12 +124,12 @@ static MPSiteKey mpw_siteKey_v0(
return siteKey;
}
static const char *mpw_sitePassword_v0(
MPSiteKey siteKey, const MPPasswordType passwordType) {
static const char *mpw_sitePasswordFromTemplate_v0(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
// Determine the template.
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 );
if (!template)
return NULL;
@ -139,7 +139,7 @@ static const char *mpw_sitePassword_v0(
}
// 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) {
sitePassword[c] = mpw_characterFromClass_v0( template[c], htons( _siteKey[c + 1] ) );
trc( " - class: %c, index: %5u (0x%02hX) => character: %c\n",
@ -150,8 +150,80 @@ static const char *mpw_sitePassword_v0(
return sitePassword;
}
const char *mpw_encrypt_v0(
MPMasterKey masterKey, const char *plainText) {
static const char *mpw_sitePasswordFromCrypt_v0(
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
size_t bufSize = strlen( plainText );
@ -175,28 +247,3 @@ const char *mpw_encrypt_v0(
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(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext);
const char *mpw_encrypt_v0(
MPMasterKey masterKey, const char *plainText);
const char *mpw_decrypt_v0(
MPMasterKey masterKey, const char *cipherText);
const char *mpw_sitePasswordFromCrypt_v0(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
const char *mpw_sitePasswordFromDerive_v0(
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.
static MPMasterKey mpw_masterKey_v1(
@ -52,11 +54,11 @@ static MPSiteKey mpw_siteKey_v1(
return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );
}
static const char *mpw_sitePassword_v1(
MPSiteKey siteKey, const MPPasswordType passwordType) {
static const char *mpw_sitePasswordFromTemplate_v1(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam) {
// 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 );
if (!template)
return NULL;
@ -77,14 +79,20 @@ static const char *mpw_sitePassword_v1(
return sitePassword;
}
static const char *mpw_encrypt_v1(
MPMasterKey masterKey, const char *plainText) {
static const char *mpw_sitePasswordFromCrypt_v1(
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(
MPMasterKey masterKey, const char *cipherText) {
static const char *mpw_sitePasswordFromDerive_v1(
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.
MPMasterKey mpw_masterKey_v1(
const char *fullName, const char *masterPassword);
const char *mpw_sitePassword_v1(
MPSiteKey siteKey, const MPPasswordType passwordType);
const char *mpw_encrypt_v1(
MPMasterKey masterKey, const char *plainText);
const char *mpw_decrypt_v1(
MPMasterKey masterKey, const char *cipherText);
const char *mpw_sitePasswordFromTemplate_v1(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_sitePasswordFromCrypt_v1(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
const char *mpw_sitePasswordFromDerive_v1(
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.
static MPMasterKey mpw_masterKey_v2(
@ -76,7 +78,7 @@ static MPSiteKey mpw_siteKey_v2(
trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )\n",
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 );
if (!siteKey) {
err( "Could not allocate site key: %s\n", strerror( errno ) );
@ -87,20 +89,26 @@ static MPSiteKey mpw_siteKey_v2(
return siteKey;
}
static const char *mpw_sitePassword_v2(
MPSiteKey siteKey, const MPPasswordType passwordType) {
static const char *mpw_sitePasswordFromTemplate_v2(
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(
MPMasterKey masterKey, const char *plainText) {
static const char *mpw_sitePasswordFromCrypt_v2(
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(
MPMasterKey masterKey, const char *cipherText) {
static const char *mpw_sitePasswordFromDerive_v2(
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(
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext);
const char *mpw_sitePassword_v2(
MPSiteKey siteKey, const MPPasswordType passwordType);
const char *mpw_encrypt_v2(
MPMasterKey masterKey, const char *plainText);
const char *mpw_decrypt_v2(
MPMasterKey masterKey, const char *cipherText);
const char *mpw_sitePasswordFromTemplate_v2(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *resultParam);
const char *mpw_sitePasswordFromCrypt_v2(
MPMasterKey masterKey, MPSiteKey siteKey, const MPResultType resultType, const char *cipherText);
const char *mpw_sitePasswordFromDerive_v2(
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.
static MPMasterKey mpw_masterKey_v3(
@ -61,7 +63,7 @@ static MPMasterKey mpw_masterKey_v3(
// Calculate the master key.
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 );
if (!masterKey) {
err( "Could not allocate master key: %s\n", strerror( errno ) );
@ -73,26 +75,32 @@ static MPMasterKey mpw_masterKey_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) {
return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );
}
static const char *mpw_sitePassword_v3(
MPSiteKey siteKey, const MPPasswordType passwordType) {
static const char *mpw_sitePasswordFromTemplate_v3(
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(
MPMasterKey masterKey, const char *plainText) {
static const char *mpw_sitePasswordFromCrypt_v3(
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(
MPMasterKey masterKey, const char *cipherText) {
static const char *mpw_sitePasswordFromDerive_v3(
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,
.avatar = 0,
.defaultType = MPPasswordTypeDefault,
.defaultType = MPResultTypeDefault,
.lastUsed = 0,
.sites_count = 0,
@ -49,7 +49,7 @@ MPMarshalledUser *mpw_marshall_user(
};
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) {
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count ))
@ -59,7 +59,7 @@ MPMarshalledSite *mpw_marshall_site(
*site = (MPMarshalledSite){
.name = strdup( siteName ),
.content = NULL,
.type = passwordType,
.type = resultType,
.counter = siteCounter,
.algorithm = algorithmVersion,
@ -171,13 +171,9 @@ static bool mpw_marshall_write_flat(
return false;
}
if (site->type & MPPasswordTypeClassGenerated) {
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, site->counter, MPKeyPurposeAuthentication, NULL, site->algorithm );
content = mpw_sitePassword( siteKey, site->type, site->algorithm );
mpw_free( siteKey, MPSiteKeySize );
}
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
content = mpw_decrypt( masterKey, site->content, site->algorithm );
if (site->type & MPResultTypeClassTemplate)
content = mpw_siteResult( masterKey, site->name, site->counter,
MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm );
}
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
// Redacted
@ -255,13 +251,9 @@ static bool mpw_marshall_write_json(
return false;
}
if (site->type & MPPasswordTypeClassGenerated) {
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, site->counter, MPKeyPurposeAuthentication, NULL, site->algorithm );
content = mpw_sitePassword( siteKey, site->type, site->algorithm );
mpw_free( siteKey, MPSiteKeySize );
}
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
content = mpw_decrypt( masterKey, site->content, site->algorithm );
if (site->type & MPResultTypeClassTemplate)
content = mpw_siteResult( masterKey, site->name, site->counter,
MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm );
}
else if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content ))
// Redacted
@ -294,10 +286,8 @@ static bool mpw_marshall_write_json(
if (!user->redacted) {
// Clear Text
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name,
MPCounterValueInitial, MPKeyPurposeRecovery, question->keyword, site->algorithm );
const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site->algorithm );
mpw_free( siteKey, MPSiteKeySize );
const char *answer = mpw_siteResult( masterKey, site->name, MPCounterValueInitial,
MPKeyPurposeRecovery, question->keyword, MPResultTypeTemplatePhrase, NULL, site->algorithm );
if (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 );
case MPMarshallFormatJSON:
return mpw_marshall_write_json( out, user, error );
default:
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) };
return false;
}
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) };
return false;
}
static MPMarshalledUser *mpw_marshall_read_flat(
@ -344,7 +334,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
unsigned int format = 0, avatar = 0;
char *fullName = NULL, *keyID = NULL;
MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1;
MPPasswordType defaultType = MPPasswordTypeDefault;
MPResultType defaultType = MPResultTypeDefault;
bool headerStarted = false, headerEnded = false, importRedacted = false;
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) {
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 ) };
return NULL;
}
defaultType = (MPPasswordType)value;
defaultType = (MPResultType)value;
}
if (strcmp( headerName, "Passwords" ) == 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) {
MPPasswordType siteType = (MPPasswordType)atoi( str_type );
MPResultType siteType = (MPResultType)atoi( str_type );
if (!mpw_nameForType( siteType )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %s", siteName, str_type ) };
return NULL;
@ -518,7 +508,8 @@ static MPMarshalledUser *mpw_marshall_read_flat(
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
// Redacted
@ -587,7 +578,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
return NULL;
}
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 )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) };
return NULL;
@ -629,7 +620,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
return NULL;
}
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 )) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site type: %s: %u", siteName, siteType ) };
return NULL;
@ -673,7 +664,8 @@ static MPMarshalledUser *mpw_marshall_read_json(
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
// Redacted
@ -699,10 +691,10 @@ MPMarshalledUser *mpw_marshall_read(
return mpw_marshall_read_flat( in, masterPassword, error );
case MPMarshallFormatJSON:
return mpw_marshall_read_json( in, masterPassword, error );
default:
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) };
return NULL;
}
*error = (MPMarshallError){ MPMarshallErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) };
return NULL;
}
const MPMarshallFormat mpw_formatWithName(

View File

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

View File

@ -29,28 +29,30 @@
#include "mpw-types.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.
if (strlen( typeName ) == 1) {
if ('x' == typeName[0])
return MPPasswordTypeGeneratedMaximum;
return MPResultTypeTemplateMaximum;
if ('l' == typeName[0])
return MPPasswordTypeGeneratedLong;
return MPResultTypeTemplateLong;
if ('m' == typeName[0])
return MPPasswordTypeGeneratedMedium;
return MPResultTypeTemplateMedium;
if ('b' == typeName[0])
return MPPasswordTypeGeneratedBasic;
return MPResultTypeTemplateBasic;
if ('s' == typeName[0])
return MPPasswordTypeGeneratedShort;
return MPResultTypeTemplateShort;
if ('i' == typeName[0])
return MPPasswordTypeGeneratedPIN;
return MPResultTypeTemplatePIN;
if ('n' == typeName[0])
return MPPasswordTypeGeneratedName;
return MPResultTypeTemplateName;
if ('P' == typeName[0])
return MPPasswordTypeStoredPersonal;
return MPResultTypeStatePersonal;
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.
@ -64,71 +66,77 @@ const MPPasswordType mpw_typeWithName(const char *typeName) {
stdTypeName[stdTypeNameSize] = '\0';
// Find what password type is represented by the type name.
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPhrase;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedMaximum;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedLong;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedMedium;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedBasic;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedShort;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPIN;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedName ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedName;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPhrase;
if (strncmp( mpw_nameForType( MPResultTypeTemplateMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplateMaximum;
if (strncmp( mpw_nameForType( MPResultTypeTemplateLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplateLong;
if (strncmp( mpw_nameForType( MPResultTypeTemplateMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplateMedium;
if (strncmp( mpw_nameForType( MPResultTypeTemplateBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplateBasic;
if (strncmp( mpw_nameForType( MPResultTypeTemplateShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplateShort;
if (strncmp( mpw_nameForType( MPResultTypeTemplatePIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplatePIN;
if (strncmp( mpw_nameForType( MPResultTypeTemplateName ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplateName;
if (strncmp( mpw_nameForType( MPResultTypeTemplatePhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPResultTypeTemplatePhrase;
if (strncmp( mpw_nameForType( MPResultTypeStatePersonal ), stdTypeName, strlen( stdTypeName ) ) == 0)
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 );
return (MPPasswordType)ERR;
return (MPResultType)ERR;
}
const char *mpw_nameForType(MPPasswordType passwordType) {
const char *mpw_nameForType(MPResultType resultType) {
switch (passwordType) {
case MPPasswordTypeGeneratedMaximum:
switch (resultType) {
case MPResultTypeTemplateMaximum:
return "maximum";
case MPPasswordTypeGeneratedLong:
case MPResultTypeTemplateLong:
return "long";
case MPPasswordTypeGeneratedMedium:
case MPResultTypeTemplateMedium:
return "medium";
case MPPasswordTypeGeneratedBasic:
case MPResultTypeTemplateBasic:
return "basic";
case MPPasswordTypeGeneratedShort:
case MPResultTypeTemplateShort:
return "short";
case MPPasswordTypeGeneratedPIN:
case MPResultTypeTemplatePIN:
return "pin";
case MPPasswordTypeGeneratedName:
case MPResultTypeTemplateName:
return "name";
case MPPasswordTypeGeneratedPhrase:
case MPResultTypeTemplatePhrase:
return "phrase";
case MPPasswordTypeStoredPersonal:
case MPResultTypeStatePersonal:
return "personal";
case MPPasswordTypeStoredDevice:
case MPResultTypeStateDevice:
return "device";
case MPResultTypeDeriveKey:
return "key";
default: {
dbg( "Unknown password type: %d\n", passwordType );
dbg( "Unknown password type: %d\n", resultType );
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 );
return NULL;
}
switch (type) {
case MPPasswordTypeGeneratedMaximum:
case MPResultTypeTemplateMaximum:
return mpw_alloc_array( count, const char *,
"anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" );
case MPPasswordTypeGeneratedLong:
case MPResultTypeTemplateLong:
return mpw_alloc_array( count, const char *,
"CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
@ -137,22 +145,22 @@ const char **mpw_templatesForType(MPPasswordType type, size_t *count) {
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" );
case MPPasswordTypeGeneratedMedium:
case MPResultTypeTemplateMedium:
return mpw_alloc_array( count, const char *,
"CvcnoCvc", "CvcCvcno" );
case MPPasswordTypeGeneratedBasic:
case MPResultTypeTemplateBasic:
return mpw_alloc_array( count, const char *,
"aaanaaan", "aannaaan", "aaannaaa" );
case MPPasswordTypeGeneratedShort:
case MPResultTypeTemplateShort:
return mpw_alloc_array( count, const char *,
"Cvcn" );
case MPPasswordTypeGeneratedPIN:
case MPResultTypeTemplatePIN:
return mpw_alloc_array( count, const char *,
"nnnn" );
case MPPasswordTypeGeneratedName:
case MPResultTypeTemplateName:
return mpw_alloc_array( count, const char *,
"cvccvcvcv" );
case MPPasswordTypeGeneratedPhrase:
case MPResultTypeTemplatePhrase:
return mpw_alloc_array( count, const char *,
"cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" );
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;
const char **templates = mpw_templatesForType( type, &count );

View File

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

View File

@ -18,6 +18,7 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
#if MPW_COLOR
#include <unistd.h>
@ -32,6 +33,7 @@
#include "sodium.h"
#ifdef SODIUM_LIBRARY_MINIMAL
#include "crypto_stream_aes128ctr.h"
#include "crypto_kdf_blake2b.h"
#endif
#endif
@ -122,7 +124,7 @@ bool mpw_free_string(const char *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) {
if (!secret || !salt)
@ -149,7 +151,49 @@ uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_
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)
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 ) );
if (!identiconSeed)
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.
* @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,
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.
* @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);
/** Encrypt a plainBuf with the given key using AES-128-CBC.
* @return A new bufSize allocated buffer containing the cipherBuf. */

View File

@ -7,7 +7,7 @@
<keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID>
<siteName>masterpasswordapp.com</siteName>
<siteCounter>1</siteCounter>
<passwordType>GeneratedLong</passwordType>
<resultType>GeneratedLong</resultType>
<keyPurpose>Authentication</keyPurpose>
<result><!-- abstract --></result>
</case>
@ -33,12 +33,12 @@
</case>
<case id="v3_loginName" parent="v3">
<keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>wohzaqage</result>
</case>
<case id="v3_securityAnswer" parent="v3">
<keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>xin diyjiqoja hubu</result>
</case>
<case id="v3_securityAnswer_context" parent="v3_securityAnswer">
@ -46,31 +46,31 @@
<result>xogx tem cegyiva jab</result>
</case>
<case id="v3_type_maximum" parent="v3">
<passwordType>GeneratedMaximum</passwordType>
<resultType>GeneratedMaximum</resultType>
<result>W6@692^B1#&amp;@gVdSdLZ@</result>
</case>
<case id="v3_type_medium" parent="v3">
<passwordType>GeneratedMedium</passwordType>
<resultType>GeneratedMedium</resultType>
<result>Jej2$Quv</result>
</case>
<case id="v3_type_basic" parent="v3">
<passwordType>GeneratedBasic</passwordType>
<resultType>GeneratedBasic</resultType>
<result>WAo2xIg6</result>
</case>
<case id="v3_type_short" parent="v3">
<passwordType>GeneratedShort</passwordType>
<resultType>GeneratedShort</resultType>
<result>Jej2</result>
</case>
<case id="v3_type_pin" parent="v3">
<passwordType>GeneratedPIN</passwordType>
<resultType>GeneratedPIN</resultType>
<result>7662</result>
</case>
<case id="v3_type_name" parent="v3">
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>jejraquvo</result>
</case>
<case id="v3_type_phrase" parent="v3">
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>jejr quv cabsibu tam</result>
</case>
<case id="v3_counter_ceiling" parent="v3">
@ -99,12 +99,12 @@
</case>
<case id="v2_loginName" parent="v2">
<keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>wohzaqage</result>
</case>
<case id="v2_securityAnswer" parent="v2">
<keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>xin diyjiqoja hubu</result>
</case>
<case id="v2_securityAnswer_context" parent="v2_securityAnswer">
@ -112,31 +112,31 @@
<result>xogx tem cegyiva jab</result>
</case>
<case id="v2_type_maximum" parent="v2">
<passwordType>GeneratedMaximum</passwordType>
<resultType>GeneratedMaximum</resultType>
<result>W6@692^B1#&amp;@gVdSdLZ@</result>
</case>
<case id="v2_type_medium" parent="v2">
<passwordType>GeneratedMedium</passwordType>
<resultType>GeneratedMedium</resultType>
<result>Jej2$Quv</result>
</case>
<case id="v2_type_basic" parent="v2">
<passwordType>GeneratedBasic</passwordType>
<resultType>GeneratedBasic</resultType>
<result>WAo2xIg6</result>
</case>
<case id="v2_type_short" parent="v2">
<passwordType>GeneratedShort</passwordType>
<resultType>GeneratedShort</resultType>
<result>Jej2</result>
</case>
<case id="v2_type_pin" parent="v2">
<passwordType>GeneratedPIN</passwordType>
<resultType>GeneratedPIN</resultType>
<result>7662</result>
</case>
<case id="v2_type_name" parent="v2">
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>jejraquvo</result>
</case>
<case id="v2_type_phrase" parent="v2">
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>jejr quv cabsibu tam</result>
</case>
<case id="v2_counter_ceiling" parent="v2">
@ -165,12 +165,12 @@
</case>
<case id="v1_loginName" parent="v1">
<keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>wohzaqage</result>
</case>
<case id="v1_securityAnswer" parent="v1">
<keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>xin diyjiqoja hubu</result>
</case>
<case id="v1_securityAnswer_context" parent="v1_securityAnswer">
@ -178,31 +178,31 @@
<result>xogx tem cegyiva jab</result>
</case>
<case id="v1_type_maximum" parent="v1">
<passwordType>GeneratedMaximum</passwordType>
<resultType>GeneratedMaximum</resultType>
<result>W6@692^B1#&amp;@gVdSdLZ@</result>
</case>
<case id="v1_type_medium" parent="v1">
<passwordType>GeneratedMedium</passwordType>
<resultType>GeneratedMedium</resultType>
<result>Jej2$Quv</result>
</case>
<case id="v1_type_basic" parent="v1">
<passwordType>GeneratedBasic</passwordType>
<resultType>GeneratedBasic</resultType>
<result>WAo2xIg6</result>
</case>
<case id="v1_type_short" parent="v1">
<passwordType>GeneratedShort</passwordType>
<resultType>GeneratedShort</resultType>
<result>Jej2</result>
</case>
<case id="v1_type_pin" parent="v1">
<passwordType>GeneratedPIN</passwordType>
<resultType>GeneratedPIN</resultType>
<result>7662</result>
</case>
<case id="v1_type_name" parent="v1">
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>jejraquvo</result>
</case>
<case id="v1_type_phrase" parent="v1">
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>jejr quv cabsibu tam</result>
</case>
<case id="v1_counter_ceiling" parent="v1">
@ -231,12 +231,12 @@
</case>
<case id="v0_loginName" parent="v0">
<keyPurpose>Identification</keyPurpose>
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>lozwajave</result>
</case>
<case id="v0_securityAnswer" parent="v0">
<keyPurpose>Recovery</keyPurpose>
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>miy lirfijoja dubu</result>
</case>
<case id="v0_securityAnswer_context" parent="v0_securityAnswer">
@ -244,31 +244,31 @@
<result>movm bex gevrica jaf</result>
</case>
<case id="v0_type_maximum" parent="v0">
<passwordType>GeneratedMaximum</passwordType>
<resultType>GeneratedMaximum</resultType>
<result>w1!3bA3icmRAc)SS@lwl</result>
</case>
<case id="v0_type_medium" parent="v0">
<passwordType>GeneratedMedium</passwordType>
<resultType>GeneratedMedium</resultType>
<result>Fej7]Jug</result>
</case>
<case id="v0_type_basic" parent="v0">
<passwordType>GeneratedBasic</passwordType>
<resultType>GeneratedBasic</resultType>
<result>wvH7irC1</result>
</case>
<case id="v0_type_short" parent="v0">
<passwordType>GeneratedShort</passwordType>
<resultType>GeneratedShort</resultType>
<result>Fej7</result>
</case>
<case id="v0_type_pin" parent="v0">
<passwordType>GeneratedPIN</passwordType>
<resultType>GeneratedPIN</resultType>
<result>2117</result>
</case>
<case id="v0_type_name" parent="v0">
<passwordType>GeneratedName</passwordType>
<resultType>GeneratedName</resultType>
<result>fejrajugo</result>
</case>
<case id="v0_type_phrase" parent="v0">
<passwordType>GeneratedPhrase</passwordType>
<resultType>GeneratedPhrase</resultType>
<result>fejr jug gabsibu bax</result>
</case>
<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 *siteName = "masterpasswordapp.com";
const MPCounterValue siteCounter = MPCounterValueDefault;
const MPPasswordType passwordType = MPPasswordTypeDefault;
const MPResultType resultType = MPResultTypeDefault;
const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
const char *keyContext = NULL;
struct timeval startTime;
@ -69,7 +69,7 @@ int main(int argc, char *const argv[]) {
}
mpw_getTime( &startTime );
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)
fprintf( stderr, "\rhmac-sha-256: iteration %d / %d (%.0f%%)..", i, iterations, percent );
@ -113,12 +113,9 @@ int main(int argc, char *const argv[]) {
break;
}
MPSiteKey siteKey = mpw_siteKey(
masterKey, siteName, siteCounter, keyPurpose, keyContext, MPAlgorithmVersionCurrent );
free( (void *)mpw_sitePassword(
siteKey, passwordType, MPAlgorithmVersionCurrent ) );
free( (void *)mpw_siteResult(
masterKey, siteName, siteCounter, keyPurpose, keyContext, resultType, NULL, MPAlgorithmVersionCurrent ) );
free( (void *)masterKey );
free( (void *)siteKey );
if (modff(100.f * i / iterations, &percent) == 0)
fprintf( stderr, "\rmpw: iteration %d / %d (%.0f%%)..", i, iterations, percent );

View File

@ -47,7 +47,8 @@ static void usage() {
" i, pin | 4 numbers.\n"
" n, name | 9 letter name.\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( ""
" -c counter The value of the counter.\n"
" Defaults to 1.\n\n" );
@ -56,7 +57,8 @@ static void usage() {
" Defaults to %s in env or %d.\n\n",
MPAlgorithmVersionFirst, MPAlgorithmVersionLast, MP_ENV_algorithm, MPAlgorithmVersionCurrent );
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( ""
" -p purpose The purpose of the generated token.\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[]) {
// 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;
MPPasswordType passwordType = MPPasswordTypeDefault;
MPResultType resultType = MPResultTypeDefault;
MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
MPMarshallFormat sitesFormat = MPMarshallFormatDefault;
@ -160,13 +162,13 @@ int main(int argc, char *const argv[]) {
// Read the environment.
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;
fullNameArg = mpw_getenv( MP_ENV_fullName );
algorithmVersionArg = mpw_getenv( MP_ENV_algorithm );
// 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) {
case 'u':
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;
allowPasswordUpdate = true;
break;
case 'P':
case 'M':
// Passing your master password via the command-line is insecure. Testing purposes only.
masterPasswordArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break;
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;
case 'c':
siteCounterArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
@ -189,9 +194,6 @@ int main(int argc, char *const argv[]) {
case 'a':
algorithmVersionArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break;
case 's':
saveValueArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break;
case 'p':
keyPurposeArg = optarg && strlen( optarg )? strdup( optarg ): NULL;
break;
@ -342,7 +344,7 @@ int main(int argc, char *const argv[]) {
fullName = strdup( user->fullName );
masterPassword = strdup( user->masterPassword );
algorithmVersion = user->algorithm;
passwordType = user->defaultType;
resultType = user->defaultType;
sitesRedacted = user->redacted;
if (!sitesRedacted && !sitesRedactedArg)
@ -355,8 +357,8 @@ int main(int argc, char *const argv[]) {
continue;
}
mpw_free_string( saveValue );
passwordType = site->type;
mpw_free_string( resultParam );
resultType = site->type;
siteCounter = site->counter;
algorithmVersion = site->algorithm;
break;
@ -383,10 +385,6 @@ int main(int argc, char *const argv[]) {
}
algorithmVersion = (MPAlgorithmVersion)algorithmVersionInt;
}
if (saveValueArg) {
mpw_free_string( saveValue );
saveValue = strdup( saveValueArg );
}
if (keyPurposeArg) {
keyPurpose = mpw_purposeWithName( keyPurposeArg );
if (ERR == (int)keyPurpose) {
@ -399,23 +397,27 @@ int main(int argc, char *const argv[]) {
case MPKeyPurposeAuthentication:
break;
case MPKeyPurposeIdentification: {
passwordType = MPPasswordTypeGeneratedName;
resultType = MPResultTypeTemplateName;
purposeResult = "login";
break;
}
case MPKeyPurposeRecovery: {
passwordType = MPPasswordTypeGeneratedPhrase;
resultType = MPResultTypeTemplatePhrase;
purposeResult = "answer";
break;
}
}
if (passwordTypeArg) {
passwordType = mpw_typeWithName( passwordTypeArg );
if (ERR == (int)passwordType) {
ftl( "Invalid type: %s\n", passwordTypeArg );
if (resultTypeArg) {
resultType = mpw_typeWithName( resultTypeArg );
if (ERR == (int)resultType) {
ftl( "Invalid type: %s\n", resultTypeArg );
return EX_USAGE;
}
}
if (resultParamArg) {
mpw_free_string( resultParam );
resultParam = strdup( resultParamArg );
}
if (keyContextArg) {
mpw_free_string( keyContext );
keyContext = strdup( keyContextArg );
@ -423,10 +425,10 @@ int main(int argc, char *const argv[]) {
mpw_free_string( fullNameArg );
mpw_free_string( masterPasswordArg );
mpw_free_string( siteNameArg );
mpw_free_string( passwordTypeArg );
mpw_free_string( resultTypeArg );
mpw_free_string( resultParamArg );
mpw_free_string( siteCounterArg );
mpw_free_string( algorithmVersionArg );
mpw_free_string( saveValueArg );
mpw_free_string( keyPurposeArg );
mpw_free_string( keyContextArg );
mpw_free_string( sitesFormatArg );
@ -444,10 +446,10 @@ int main(int argc, char *const argv[]) {
dbg( "sitesPath : %s\n", sitesPath );
dbg( "siteName : %s\n", siteName );
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( "keyContext : %s\n", keyContext );
dbg( "passwordType : %s (%u)\n", mpw_nameForType( passwordType ), passwordType );
dbg( "algorithmVersion : %u\n", algorithmVersion );
dbg( "-----------------\n\n" );
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)
fprintf( stdout, "%s\n", site->loginName );
else if (passwordType & MPPasswordTypeClassGenerated) {
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" );
else if (resultParam && site && resultType & MPResultTypeClassState) {
mpw_free_string( site->content );
if (!(site->content = mpw_siteState( masterKey, siteName, siteCounter,
keyPurpose, keyContext, resultType, resultParam, algorithmVersion ))) {
ftl( "Couldn't encrypt site content.\n" );
mpw_free( masterKey, MPMasterKeySize );
return EX_SOFTWARE;
}
fprintf( stdout, "%s\n", sitePassword );
mpw_free_string( sitePassword );
inf( "saved.\n" );
}
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 );
if (!(site->content = mpw_encrypt( masterKey, saveValue, algorithmVersion )))
err( "Couldn't encrypt site content.\n" );
}
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;
}
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 );
return EX_SOFTWARE;
}
}
fprintf( stdout, "%s\n", content );
mpw_free_string( content );
fprintf( stdout, "%s\n", siteResult );
mpw_free_string( siteResult );
}
if (site && site->url)
inf( "See: %s\n", site->url );
mpw_free( masterKey, MPMasterKeySize );
mpw_free_string( siteName );
mpw_free_string( saveValue );
mpw_free_string( resultParam );
mpw_free_string( keyContext );
// Update the mpsites file.
if (user) {
// 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)
site = mpw_marshall_site( user, siteName, passwordType, siteCounter, algorithmVersion );
site = mpw_marshall_site( user, siteName, resultType, siteCounter, algorithmVersion );
else {
site->type = passwordType;
site->type = resultType;
site->counter = siteCounter;
site->algorithm = algorithmVersion;
}
}
else if (keyPurpose == MPKeyPurposeIdentification && site) {
// TODO: We're not persisting the passwordType of the generated login
if (passwordType & MPPasswordTypeClassGenerated)
// TODO: We're not persisting the resultType of the generated login
if (resultType & MPResultTypeClassTemplate)
site->loginGenerated = true;
}
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;
for (size_t q = 0; q < site->questions_count; ++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 *siteName = mpw_xmlTestCaseString( testCase, "siteName" );
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 *keyContext = mpw_xmlTestCaseString( testCase, "keyContext" );
xmlChar *result = mpw_xmlTestCaseString( testCase, "result" );
MPPasswordType siteType = mpw_typeWithName( (char *)passwordTypeString );
MPKeyPurpose siteVariant = mpw_purposeWithName( (char *)keyPurposeString );
MPResultType resultType = mpw_typeWithName( (char *)resultTypeString );
MPKeyPurpose keyPurpose = mpw_purposeWithName( (char *)keyPurposeString );
// Run the test case.
fprintf( stdout, "test case %s... ", id );
@ -54,12 +54,9 @@ int main(int argc, char *const argv[]) {
}
// 2. calculate the site password.
MPSiteKey siteKey = mpw_siteKey(
masterKey, (char *)siteName, siteCounter, siteVariant, (char *)keyContext, algorithm );
const char *sitePassword = mpw_sitePassword(
siteKey, siteType, algorithm );
const char *sitePassword = mpw_siteResult(
masterKey, (char *)siteName, siteCounter, keyPurpose, (char *)keyContext, resultType, NULL, algorithm );
mpw_free( masterKey, MPMasterKeySize );
mpw_free( siteKey, MPSiteKeySize );
if (!sitePassword) {
ftl( "Couldn't derive site password.\n" );
continue;
@ -81,7 +78,7 @@ int main(int argc, char *const argv[]) {
xmlFree( masterPassword );
xmlFree( keyID );
xmlFree( siteName );
xmlFree( passwordTypeString );
xmlFree( resultTypeString );
xmlFree( keyPurposeString );
xmlFree( keyContext );
xmlFree( result );

View File

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