diff --git a/MasterPassword/C/build b/MasterPassword/C/build index 9d1d038a..214d2bdd 100755 --- a/MasterPassword/C/build +++ b/MasterPassword/C/build @@ -1,3 +1,5 @@ #!/usr/bin/env bash -e -gcc types.c -o types.o -gcc -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"types.o" -l"crypto" -L"lib/scrypt" mpw.c -o mpw +# Run with -DDEBUG to enable trace-level output. + +gcc -c types.c -o types.o "$@" +gcc -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"types.o" -l"crypto" -L"." -L"lib/scrypt" mpw.c -o mpw "$@" diff --git a/MasterPassword/C/mpw.c b/MasterPassword/C/mpw.c index 354b65e3..e0980c2f 100644 --- a/MasterPassword/C/mpw.c +++ b/MasterPassword/C/mpw.c @@ -63,6 +63,7 @@ int main(int argc, char *const argv[]) { const char *userName = getenv( MP_env_username ); const char *masterPassword = NULL; const char *siteName = NULL; + MPElementType siteType = MPElementTypeGeneratedLong; const char *siteTypeString = getenv( MP_env_sitetype ); uint32_t siteCounter = 1; const char *siteCounterString = getenv( MP_env_sitecounter ); @@ -83,16 +84,16 @@ int main(int argc, char *const argv[]) { case '?': switch (optopt) { case 'u': - fprintf (stderr, "Missing user name to option: -%c\n", optopt); + fprintf(stderr, "Missing user name to option: -%c\n", optopt); break; case 't': - fprintf (stderr, "Missing type name to option: -%c\n", optopt); + fprintf(stderr, "Missing type name to option: -%c\n", optopt); break; case 'c': - fprintf (stderr, "Missing counter value to option: -%c\n", optopt); + fprintf(stderr, "Missing counter value to option: -%c\n", optopt); break; default: - fprintf (stderr, "Unknown option: -%c\n", optopt); + fprintf(stderr, "Unknown option: -%c\n", optopt); } return 1; default: @@ -103,29 +104,36 @@ int main(int argc, char *const argv[]) { // Convert and validate input. if (!userName) { - fprintf (stderr, "Missing user name.\n"); + fprintf(stderr, "Missing user name.\n"); return 1; } + trc("userName: %s\n", userName); if (!siteName) { - fprintf (stderr, "Missing site name.\n"); + fprintf(stderr, "Missing site name.\n"); return 1; } + trc("siteName: %s\n", siteName); if (siteCounterString) siteCounter = atoi( siteCounterString ); if (siteCounter < 1) { - fprintf (stderr, "Invalid site counter: %d\n", siteCounter); + fprintf(stderr, "Invalid site counter: %d\n", siteCounter); return 1; } + trc("siteCounter: %d\n", siteCounter); + if (siteTypeString) + siteType = TypeWithName( siteTypeString ); + trc("siteType: %d (%s)\n", siteType, siteTypeString); // Read the master password. char *mpwConfigPath = homedir(".mpw"); if (!mpwConfigPath) { - fprintf (stderr, "Couldn't resolve path for configuration file: %d\n", errno); + fprintf(stderr, "Couldn't resolve path for configuration file: %d\n", errno); return 1; } + trc("mpwConfigPath: %s\n", mpwConfigPath); FILE *mpwConfig = fopen(mpwConfigPath, "r"); if (!mpwConfig) { - fprintf (stderr, "Couldn't open configuration file: %s: %d\n", mpwConfigPath, errno); + fprintf(stderr, "Couldn't open configuration file: %s: %d\n", mpwConfigPath, errno); return 1; } free(mpwConfigPath); @@ -138,25 +146,26 @@ int main(int argc, char *const argv[]) { break; } if (!masterPassword) { - fprintf (stderr, "Missing master password for user: %s\n", userName); + fprintf(stderr, "Missing master password for user: %s\n", userName); return 1; } + trc("masterPassword: %s\n", masterPassword); // Calculate the master key. uint8_t *masterKey = malloc( MP_dkLen ); if (!masterKey) { - fprintf (stderr, "Could not allocate master key: %d\n", errno); + fprintf(stderr, "Could not allocate master key: %d\n", errno); return 1; } const uint32_t n_userNameLength = htonl(strlen(userName)); char *masterKeySalt = NULL; size_t masterKeySaltLength = asprintf(&masterKeySalt, "com.lyndir.masterpassword%s%s", (const char *) &n_userNameLength, userName); if (!masterKeySalt) { - fprintf (stderr, "Could not allocate master key salt: %d\n", errno); + fprintf(stderr, "Could not allocate master key salt: %d\n", errno); return 1; } if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) { - fprintf (stderr, "Could not generate master key: %d\n", errno); + fprintf(stderr, "Could not generate master key: %d\n", errno); return 1; } memset(masterKeySalt, 0, masterKeySaltLength); @@ -167,7 +176,7 @@ int main(int argc, char *const argv[]) { char *sitePasswordInfo = NULL; size_t sitePasswordInfoLength = asprintf(&sitePasswordInfo, "com.lyndir.masterpassword%s%s%s", (const char *) &n_siteNameLength, siteName, (const char *) &n_siteCounter); if (!sitePasswordInfo) { - fprintf (stderr, "Could not allocate site seed: %d\n", errno); + fprintf(stderr, "Could not allocate site seed: %d\n", errno); return 1; } uint8_t sitePasswordSeed[32]; @@ -178,15 +187,16 @@ int main(int argc, char *const argv[]) { free(sitePasswordInfo); // Determine the cipher. - const char *cipher = CipherForType(siteType, sitePasswordSeed); - //trc(@"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher); + const char *cipher = CipherForType(siteType, sitePasswordSeed[0]); + trc("type %s, cipher: %s\n", siteTypeString, cipher); // Encode the password from the seed using the cipher. //NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher."); char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char)); - for (int c = 0; c < strlen(cipher); ++c) - //trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character); + for (int c = 0; c < strlen(cipher); ++c) { sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]); + trc("class %c, character: %c\n", cipher[c], sitePassword[c]); + } memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed)); // Output the password. diff --git a/MasterPassword/C/types.c b/MasterPassword/C/types.c index 983f958f..5e5eb589 100644 --- a/MasterPassword/C/types.c +++ b/MasterPassword/C/types.c @@ -6,58 +6,116 @@ // Copyright (c) 2012 Lyndir. All rights reserved. // +#include #include +#include +#include #include "types.h" -const char *CipherForType(MPElementType type, char seedByte) { +const MPElementType TypeWithName(const char *typeName) { + char lowerTypeName[strlen(typeName)]; + strcpy(lowerTypeName, typeName); + for (char *tN = lowerTypeName; *tN; ++tN) + *tN = tolower(*tN); + + if (0 == strcmp(lowerTypeName, "x") || 0 == strcmp(lowerTypeName, "max") || 0 == strcmp(lowerTypeName, "maximum")) + return MPElementTypeGeneratedMaximum; + if (0 == strcmp(lowerTypeName, "l") || 0 == strcmp(lowerTypeName, "long")) + return MPElementTypeGeneratedLong; + if (0 == strcmp(lowerTypeName, "m") || 0 == strcmp(lowerTypeName, "med") || 0 == strcmp(lowerTypeName, "medium")) + return MPElementTypeGeneratedMedium; + if (0 == strcmp(lowerTypeName, "b") || 0 == strcmp(lowerTypeName, "basic")) + return MPElementTypeGeneratedBasic; + if (0 == strcmp(lowerTypeName, "s") || 0 == strcmp(lowerTypeName, "short")) + return MPElementTypeGeneratedShort; + if (0 == strcmp(lowerTypeName, "p") || 0 == strcmp(lowerTypeName, "pin")) + return MPElementTypeGeneratedPIN; + + fprintf(stderr, "Not a generated type name: %s", lowerTypeName); + abort(); +} + +const char *CipherForType(MPElementType type, uint8_t seedByte) { if (!(type & MPElementTypeClassGenerated)) { fprintf(stderr, "Not a generated type: %d", type); abort(); } switch (type) { - case MPElementTypeGeneratedMaximum: - char *ciphers = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" }; + case MPElementTypeGeneratedMaximum: { + char *ciphers[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" }; return ciphers[seedByte % 2]; - case MPElementTypeGeneratedLong: - char *ciphers = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" }; + } + case MPElementTypeGeneratedLong: { + char *ciphers[] = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" }; return ciphers[seedByte % 21]; - case MPElementTypeGeneratedMedium: - char *ciphers = { "CvcnoCvc", "CvcCvcno" }; + } + case MPElementTypeGeneratedMedium: { + char *ciphers[] = { "CvcnoCvc", "CvcCvcno" }; return ciphers[seedByte % 2]; - case MPElementTypeGeneratedBasic: - char *ciphers = { "aaanaaan", "aannaaan", "aaannaaa" }; + } + case MPElementTypeGeneratedBasic: { + char *ciphers[] = { "aaanaaan", "aannaaan", "aaannaaa" }; return ciphers[seedByte % 3]; - case MPElementTypeGeneratedShort: + } + case MPElementTypeGeneratedShort: { return "Cvcn"; - case MPElementTypeGeneratedPIN: + } + case MPElementTypeGeneratedPIN: { return "nnnn"; + } + default: { + fprintf(stderr, "Unknown generated type: %d", type); + abort(); + } } } -const char CharacterFromClass(char characterClass, char seedByte) { +const char CharacterFromClass(char characterClass, uint8_t seedByte) { + const char *classCharacters; switch (characterClass) { - case 'V': - return "AEIOU"[seedByte]; - case 'C': - return "BCDFGHJKLMNPQRSTVWXYZ"[seedByte]; - case 'v': - return "aeiou"[seedByte]; - case 'c': - return "bcdfghjklmnpqrstvwxyz"[seedByte]; - case 'A': - return "AEIOUBCDFGHJKLMNPQRSTVWXYZ"[seedByte]; - case 'a': - return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"[seedByte]; - case 'n': - return "0123456789"[seedByte]; - case 'o': - return "@&%?,=[]_:-+*$#!'^~;()/."[seedByte]; - case 'x': - return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()"[seedByte]; + case 'V': { + classCharacters = "AEIOU"; + break; + } + case 'C': { + classCharacters = "BCDFGHJKLMNPQRSTVWXYZ"; + break; + } + case 'v': { + classCharacters = "aeiou"; + break; + } + case 'c': { + classCharacters = "bcdfghjklmnpqrstvwxyz"; + break; + } + case 'A': { + classCharacters = "AEIOUBCDFGHJKLMNPQRSTVWXYZ"; + break; + } + case 'a': { + classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"; + break; + } + case 'n': { + classCharacters = "0123456789"; + break; + } + case 'o': { + classCharacters = "@&%?,=[]_:-+*$#!'^~;()/."; + break; + } + case 'x': { + classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()"; + break; + } + default: { + fprintf(stderr, "Unknown character class: %c", characterClass); + abort(); + } } - fprintf(stderr, "Unknown character class: %c", characterClass); - abort(); + return classCharacters[seedByte % strlen(classCharacters)]; } diff --git a/MasterPassword/C/types.h b/MasterPassword/C/types.h index 03ab96e5..6fa5a5c2 100644 --- a/MasterPassword/C/types.h +++ b/MasterPassword/C/types.h @@ -6,27 +6,27 @@ // Copyright (c) 2012 Lyndir. All rights reserved. // -typedef NS_ENUM(NSUInteger, MPElementContentType) { +typedef enum { MPElementContentTypePassword, MPElementContentTypeNote, MPElementContentTypePicture, -}; +} MPElementContentType; -typedef NS_ENUM(NSUInteger, MPElementTypeClass) { +typedef enum { /** Generate the password. */ - MPElementTypeClassGenerated = 1 << 4, + MPElementTypeClassGenerated = 1 << 4, /** Store the password. */ - MPElementTypeClassStored = 1 << 5, -}; + MPElementTypeClassStored = 1 << 5, +} MPElementTypeClass; -typedef NS_ENUM(NSUInteger, MPElementFeature) { +typedef enum { /** Export the key-protected content data. */ - MPElementFeatureExportContent = 1 << 10, + MPElementFeatureExportContent = 1 << 10, /** Never export content. */ - MPElementFeatureDevicePrivate = 1 << 11, -}; + MPElementFeatureDevicePrivate = 1 << 11, +} MPElementFeature; -typedef NS_ENUM(NSUInteger, MPElementType) { +typedef enum { MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0, MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0, MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0, @@ -36,7 +36,14 @@ typedef NS_ENUM(NSUInteger, MPElementType) { MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent, MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate, -}; +} MPElementType; -extern const char *CipherForType(MPElementType type, char seedByte); -extern const char CharacterFromClass(char characterClass, char seedByte); +#ifdef DEBUG +#define trc(...) fprintf(stderr, __VA_ARGS__) +#else +#define trc(...) do {} while (0) +#endif + +const MPElementType TypeWithName(const char *typeName); +const char *CipherForType(MPElementType type, uint8_t seedByte); +const char CharacterFromClass(char characterClass, uint8_t seedByte);