2
0

Define type for siteCounter, add support for saving hybrid passwords.

This commit is contained in:
Maarten Billemont
2017-08-07 20:27:08 -04:00
parent b26f5a82d7
commit ee50a4d025
13 changed files with 208 additions and 133 deletions

View File

@@ -46,7 +46,7 @@ MPMasterKey mpw_masterKey(const char *fullName, const char *masterPassword, cons
}
MPSiteKey mpw_siteKey(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) {
trc( "-- mpw_siteKey (algorithm: %u)\n", algorithmVersion );

View File

@@ -45,7 +45,7 @@ MPMasterKey mpw_masterKey(
/** Derive the site key for a user's site from the given master key and site parameters.
* @return A new MPSiteKeySize-byte allocated buffer or NULL if an error occurred. */
MPSiteKey mpw_siteKey(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion);
/** Encode a password for the site from the given site key.

View File

@@ -82,12 +82,14 @@ static MPMasterKey mpw_masterKey_v0(
}
static MPSiteKey mpw_siteKey_v0(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext) {
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
trc( "keyScope: %s\n", keyScope );
// TODO: Implement MPCounterValueTOTP
// Calculate the site seed.
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
keyScope, mpw_hex_l( htonl( mpw_utf8_strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),

View File

@@ -31,7 +31,7 @@
MPMasterKey mpw_masterKey_v0(
const char *fullName, const char *masterPassword);
MPSiteKey mpw_siteKey_v0(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext);
const char *mpw_encrypt_v0(
MPMasterKey masterKey, const char *plainText);
@@ -46,7 +46,7 @@ static MPMasterKey mpw_masterKey_v1(
}
static MPSiteKey mpw_siteKey_v1(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext) {
return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext );

View File

@@ -45,12 +45,14 @@ static MPMasterKey mpw_masterKey_v2(
}
static MPSiteKey mpw_siteKey_v2(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext) {
const char *keyScope = mpw_scopeForPurpose( keyPurpose );
trc( "keyScope: %s\n", keyScope );
// TODO: Implement MPCounterValueTOTP
// Calculate the site seed.
trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s\n",
keyScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName, mpw_hex_l( htonl( siteCounter ) ),

View File

@@ -29,7 +29,7 @@
// Inherited functions.
MPSiteKey mpw_siteKey_v2(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext);
const char *mpw_sitePassword_v2(
MPSiteKey siteKey, const MPPasswordType passwordType);
@@ -73,7 +73,7 @@ static MPMasterKey mpw_masterKey_v3(
}
static MPSiteKey mpw_siteKey_v3(
MPMasterKey masterKey, const char *siteName, const uint32_t siteCounter,
MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter,
const MPKeyPurpose keyPurpose, const char *keyContext) {
return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext );

View File

@@ -50,7 +50,7 @@ MPMarshalledUser *mpw_marshall_user(
MPMarshalledSite *mpw_marshall_site(
MPMarshalledUser *user, const char *siteName, const MPPasswordType passwordType,
const uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion) {
const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) {
if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count ))
return NULL;
@@ -294,7 +294,8 @@ static bool mpw_marshall_write_json(
if (!user->redacted) {
// Clear Text
MPSiteKey siteKey = mpw_siteKey( masterKey, site->name, 1, MPKeyPurposeRecovery, question->keyword, site->algorithm );
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 );
if (answer)
@@ -482,11 +483,11 @@ static MPMarshalledUser *mpw_marshall_read_flat(
return NULL;
}
long long int value = atoll( str_counter );
if (value < 0 || value > UINT32_MAX) {
if (value < MPCounterValueFirst || value > MPCounterValueLast) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site counter: %s: %s", siteName, str_counter ) };
return NULL;
}
uint32_t siteCounter = (uint32_t)value;
MPCounterValue siteCounter = (MPCounterValue)value;
value = atoll( str_algorithm );
if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site algorithm: %s: %s", siteName, str_algorithm ) };
@@ -634,11 +635,11 @@ static MPMarshalledUser *mpw_marshall_read_json(
return NULL;
}
value = mpw_get_json_int( json_site.val, "counter", 1 );
if (value < 0 || value > UINT32_MAX) {
if (value < MPCounterValueFirst || value > MPCounterValueLast) {
*error = (MPMarshallError){ MPMarshallErrorIllegal, mpw_str( "Invalid site counter: %s: %d", siteName, value ) };
return NULL;
}
uint32_t siteCounter = (uint32_t)value;
MPCounterValue siteCounter = (MPCounterValue)value;
const char *siteContent = mpw_get_json_string( json_site.val, "password", NULL );
const char *siteLoginName = mpw_get_json_string( json_site.val, "login_name", NULL );
bool siteLoginGenerated = mpw_get_json_boolean( json_site.val, "login_generated", false );

View File

@@ -63,7 +63,7 @@ typedef struct MPMarshalledSite {
const char *name;
const char *content;
MPPasswordType type;
uint32_t counter;
MPCounterValue counter;
MPAlgorithmVersion algorithm;
const char *loginName;
@@ -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 uint32_t siteCounter, const MPAlgorithmVersion algorithmVersion);
const char *siteName, const MPPasswordType passwordType, const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion);
MPMarshalledQuestion *mpw_marshal_question(
MPMarshalledSite *site, const char *keyword);
bool mpw_marshal_free(

View File

@@ -31,6 +31,28 @@
const MPPasswordType 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;
if ('l' == typeName[0])
return MPPasswordTypeGeneratedLong;
if ('m' == typeName[0])
return MPPasswordTypeGeneratedMedium;
if ('b' == typeName[0])
return MPPasswordTypeGeneratedBasic;
if ('s' == typeName[0])
return MPPasswordTypeGeneratedShort;
if ('i' == typeName[0])
return MPPasswordTypeGeneratedPIN;
if ('n' == typeName[0])
return MPPasswordTypeGeneratedName;
if ('P' == typeName[0])
return MPPasswordTypeStoredPersonal;
if ('D' == typeName[0])
return MPPasswordTypeStoredDevice;
}
// Lower-case and trim optionally leading "Generated" string from typeName to standardize it.
size_t stdTypeNameOffset = 0;
size_t stdTypeNameSize = strlen( typeName );
@@ -42,29 +64,23 @@ const MPPasswordType mpw_typeWithName(const char *typeName) {
stdTypeName[stdTypeNameSize] = '\0';
// Find what password type is represented by the type name.
if (0 == strcmp( "x", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPhrase;
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedMaximum;
if (0 == strcmp( "l", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedLong ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedLong;
if (0 == strcmp( "m", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedMedium ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedMedium;
if (0 == strcmp( "b", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedBasic ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedBasic;
if (0 == strcmp( "s", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedShort ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedShort;
if (0 == strcmp( "i", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedPIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPIN ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPIN;
if (0 == strcmp( "n", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedName ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedName ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedName;
if (0 == strcmp( "p", stdTypeName )
|| strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
if (strncmp( mpw_nameForType( MPPasswordTypeGeneratedPhrase ), stdTypeName, strlen( stdTypeName ) ) == 0)
return MPPasswordTypeGeneratedPhrase;
dbg( "Not a generated type name: %s\n", stdTypeName );

View File

@@ -31,13 +31,13 @@
//// Types.
#define MPMasterKeySize 64
#define MPMasterKeySize 64 /* bytes */
typedef const uint8_t *MPMasterKey;
#define MPSiteKeySize 256 / 8 // Bytes in HMAC-SHA-256
#define MPSiteKeySize (256 / 8) /* bytes */ // Size of HMAC-SHA-256
typedef const uint8_t *MPSiteKey;
typedef const char *MPKeyID;
typedef enum( unsigned int, MPKeyPurpose ) {
typedef enum( uint8_t, MPKeyPurpose ) {
/** Generate a key for authentication. */
MPKeyPurposeAuthentication,
/** Generate a name for identification. */
@@ -46,21 +46,24 @@ typedef enum( unsigned int, MPKeyPurpose ) {
MPKeyPurposeRecovery,
};
typedef enum( unsigned int, MPPasswordTypeClass ) {
// bit 4 - 9
typedef enum( uint16_t, MPPasswordTypeClass ) {
/** Generate the password. */
MPPasswordTypeClassGenerated = 1 << 4,
/** Store the password. */
MPPasswordTypeClassStored = 1 << 5,
};
typedef enum( unsigned int, MPSiteFeature ) {
// bit 10 - 15
typedef enum( uint16_t, MPSiteFeature ) {
/** Export the key-protected content data. */
MPSiteFeatureExportContent = 1 << 10,
/** Never export content. */
MPSiteFeatureDevicePrivate = 1 << 11,
};
typedef enum( unsigned int, MPPasswordType ) {
// bit 0-3 | MPPasswordTypeClass | MPSiteFeature
typedef enum( uint32_t, MPPasswordType ) {
/** pg^VMAUBk5x3p%HP%i4= */
MPPasswordTypeGeneratedMaximum = 0x0 | MPPasswordTypeClassGenerated | 0x0,
/** BiroYena8:Kixa */
@@ -86,6 +89,17 @@ typedef enum( unsigned int, MPPasswordType ) {
MPPasswordTypeDefault = MPPasswordTypeGeneratedLong,
};
typedef enum ( uint32_t, MPCounterValue ) {
/** Use a time-based counter value, resulting in a TOTP generator. */
MPCounterValueTOTP = 0,
/** The initial value for a site's counter. */
MPCounterValueInitial = 1,
MPCounterValueDefault = MPCounterValueInitial,
MPCounterValueFirst = MPCounterValueTOTP,
MPCounterValueLast = UINT32_MAX,
};
//// Type utilities.
/**