2
0

WIP - Initial complete C implementation that's still buggy and generates broken passwords, yay.

This commit is contained in:
Maarten Billemont 2014-06-07 01:27:18 -04:00
parent c4dca14800
commit 2bc357cee6
4 changed files with 143 additions and 66 deletions

View File

@ -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 "$@"

View File

@ -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.

View File

@ -6,58 +6,116 @@
// Copyright (c) 2012 Lyndir. All rights reserved.
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#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 "@&amp;%?,=[]_:-+*$#!'^~;()/."[seedByte];
case 'x':
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&amp;*()"[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();
}
}
return classCharacters[seedByte % strlen(classCharacters)];
}

View File

@ -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,
/** Store the password. */
MPElementTypeClassStored = 1 << 5,
};
} MPElementTypeClass;
typedef NS_ENUM(NSUInteger, MPElementFeature) {
typedef enum {
/** Export the key-protected content data. */
MPElementFeatureExportContent = 1 << 10,
/** Never export content. */
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);