passwordType -> resultType, add derived class and key type.
This commit is contained in:
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
@@ -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(
|
||||
|
@@ -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(
|
||||
|
@@ -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 );
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
|
@@ -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. */
|
||||
|
Reference in New Issue
Block a user