Define type for siteCounter, add support for saving hybrid passwords.
This commit is contained in:
@@ -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 );
|
||||
|
@@ -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.
|
||||
|
@@ -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 ) ),
|
||||
|
@@ -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 );
|
||||
|
@@ -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 ) ),
|
||||
|
@@ -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 );
|
||||
|
@@ -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 );
|
||||
|
@@ -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(
|
||||
|
@@ -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 );
|
||||
|
@@ -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.
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user