WIP - Initial complete C implementation that's still buggy and generates broken passwords, yay.
This commit is contained in:
parent
c4dca14800
commit
2bc357cee6
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash -e
|
#!/usr/bin/env bash -e
|
||||||
gcc types.c -o types.o
|
# Run with -DDEBUG to enable trace-level output.
|
||||||
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
|
|
||||||
|
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 "$@"
|
||||||
|
@ -63,6 +63,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
const char *userName = getenv( MP_env_username );
|
const char *userName = getenv( MP_env_username );
|
||||||
const char *masterPassword = NULL;
|
const char *masterPassword = NULL;
|
||||||
const char *siteName = NULL;
|
const char *siteName = NULL;
|
||||||
|
MPElementType siteType = MPElementTypeGeneratedLong;
|
||||||
const char *siteTypeString = getenv( MP_env_sitetype );
|
const char *siteTypeString = getenv( MP_env_sitetype );
|
||||||
uint32_t siteCounter = 1;
|
uint32_t siteCounter = 1;
|
||||||
const char *siteCounterString = getenv( MP_env_sitecounter );
|
const char *siteCounterString = getenv( MP_env_sitecounter );
|
||||||
@ -83,16 +84,16 @@ int main(int argc, char *const argv[]) {
|
|||||||
case '?':
|
case '?':
|
||||||
switch (optopt) {
|
switch (optopt) {
|
||||||
case 'u':
|
case 'u':
|
||||||
fprintf (stderr, "Missing user name to option: -%c\n", optopt);
|
fprintf(stderr, "Missing user name to option: -%c\n", optopt);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
fprintf (stderr, "Missing type name to option: -%c\n", optopt);
|
fprintf(stderr, "Missing type name to option: -%c\n", optopt);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
fprintf (stderr, "Missing counter value to option: -%c\n", optopt);
|
fprintf(stderr, "Missing counter value to option: -%c\n", optopt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf (stderr, "Unknown option: -%c\n", optopt);
|
fprintf(stderr, "Unknown option: -%c\n", optopt);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
@ -103,29 +104,36 @@ int main(int argc, char *const argv[]) {
|
|||||||
|
|
||||||
// Convert and validate input.
|
// Convert and validate input.
|
||||||
if (!userName) {
|
if (!userName) {
|
||||||
fprintf (stderr, "Missing user name.\n");
|
fprintf(stderr, "Missing user name.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
trc("userName: %s\n", userName);
|
||||||
if (!siteName) {
|
if (!siteName) {
|
||||||
fprintf (stderr, "Missing site name.\n");
|
fprintf(stderr, "Missing site name.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
trc("siteName: %s\n", siteName);
|
||||||
if (siteCounterString)
|
if (siteCounterString)
|
||||||
siteCounter = atoi( siteCounterString );
|
siteCounter = atoi( siteCounterString );
|
||||||
if (siteCounter < 1) {
|
if (siteCounter < 1) {
|
||||||
fprintf (stderr, "Invalid site counter: %d\n", siteCounter);
|
fprintf(stderr, "Invalid site counter: %d\n", siteCounter);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
trc("siteCounter: %d\n", siteCounter);
|
||||||
|
if (siteTypeString)
|
||||||
|
siteType = TypeWithName( siteTypeString );
|
||||||
|
trc("siteType: %d (%s)\n", siteType, siteTypeString);
|
||||||
|
|
||||||
// Read the master password.
|
// Read the master password.
|
||||||
char *mpwConfigPath = homedir(".mpw");
|
char *mpwConfigPath = homedir(".mpw");
|
||||||
if (!mpwConfigPath) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
trc("mpwConfigPath: %s\n", mpwConfigPath);
|
||||||
FILE *mpwConfig = fopen(mpwConfigPath, "r");
|
FILE *mpwConfig = fopen(mpwConfigPath, "r");
|
||||||
if (!mpwConfig) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
free(mpwConfigPath);
|
free(mpwConfigPath);
|
||||||
@ -138,25 +146,26 @@ int main(int argc, char *const argv[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!masterPassword) {
|
if (!masterPassword) {
|
||||||
fprintf (stderr, "Missing master password for user: %s\n", userName);
|
fprintf(stderr, "Missing master password for user: %s\n", userName);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
trc("masterPassword: %s\n", masterPassword);
|
||||||
|
|
||||||
// Calculate the master key.
|
// Calculate the master key.
|
||||||
uint8_t *masterKey = malloc( MP_dkLen );
|
uint8_t *masterKey = malloc( MP_dkLen );
|
||||||
if (!masterKey) {
|
if (!masterKey) {
|
||||||
fprintf (stderr, "Could not allocate master key: %d\n", errno);
|
fprintf(stderr, "Could not allocate master key: %d\n", errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const uint32_t n_userNameLength = htonl(strlen(userName));
|
const uint32_t n_userNameLength = htonl(strlen(userName));
|
||||||
char *masterKeySalt = NULL;
|
char *masterKeySalt = NULL;
|
||||||
size_t masterKeySaltLength = asprintf(&masterKeySalt, "com.lyndir.masterpassword%s%s", (const char *) &n_userNameLength, userName);
|
size_t masterKeySaltLength = asprintf(&masterKeySalt, "com.lyndir.masterpassword%s%s", (const char *) &n_userNameLength, userName);
|
||||||
if (!masterKeySalt) {
|
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;
|
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) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
memset(masterKeySalt, 0, masterKeySaltLength);
|
memset(masterKeySalt, 0, masterKeySaltLength);
|
||||||
@ -167,7 +176,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
char *sitePasswordInfo = NULL;
|
char *sitePasswordInfo = NULL;
|
||||||
size_t sitePasswordInfoLength = asprintf(&sitePasswordInfo, "com.lyndir.masterpassword%s%s%s", (const char *) &n_siteNameLength, siteName, (const char *) &n_siteCounter);
|
size_t sitePasswordInfoLength = asprintf(&sitePasswordInfo, "com.lyndir.masterpassword%s%s%s", (const char *) &n_siteNameLength, siteName, (const char *) &n_siteCounter);
|
||||||
if (!sitePasswordInfo) {
|
if (!sitePasswordInfo) {
|
||||||
fprintf (stderr, "Could not allocate site seed: %d\n", errno);
|
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
uint8_t sitePasswordSeed[32];
|
uint8_t sitePasswordSeed[32];
|
||||||
@ -178,15 +187,16 @@ int main(int argc, char *const argv[]) {
|
|||||||
free(sitePasswordInfo);
|
free(sitePasswordInfo);
|
||||||
|
|
||||||
// Determine the cipher.
|
// Determine the cipher.
|
||||||
const char *cipher = CipherForType(siteType, sitePasswordSeed);
|
const char *cipher = CipherForType(siteType, sitePasswordSeed[0]);
|
||||||
//trc(@"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher);
|
trc("type %s, cipher: %s\n", siteTypeString, cipher);
|
||||||
|
|
||||||
// Encode the password from the seed using the cipher.
|
// Encode the password from the seed using the cipher.
|
||||||
//NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher.");
|
//NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher.");
|
||||||
char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
|
char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
|
||||||
for (int c = 0; c < strlen(cipher); ++c)
|
for (int c = 0; c < strlen(cipher); ++c) {
|
||||||
//trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character);
|
|
||||||
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
|
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
|
||||||
|
trc("class %c, character: %c\n", cipher[c], sitePassword[c]);
|
||||||
|
}
|
||||||
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
|
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
|
||||||
|
|
||||||
// Output the password.
|
// Output the password.
|
||||||
|
@ -6,58 +6,116 @@
|
|||||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include "types.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)) {
|
if (!(type & MPElementTypeClassGenerated)) {
|
||||||
fprintf(stderr, "Not a generated type: %d", type);
|
fprintf(stderr, "Not a generated type: %d", type);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MPElementTypeGeneratedMaximum:
|
case MPElementTypeGeneratedMaximum: {
|
||||||
char *ciphers = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
char *ciphers[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
||||||
return ciphers[seedByte % 2];
|
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];
|
return ciphers[seedByte % 21];
|
||||||
case MPElementTypeGeneratedMedium:
|
}
|
||||||
char *ciphers = { "CvcnoCvc", "CvcCvcno" };
|
case MPElementTypeGeneratedMedium: {
|
||||||
|
char *ciphers[] = { "CvcnoCvc", "CvcCvcno" };
|
||||||
return ciphers[seedByte % 2];
|
return ciphers[seedByte % 2];
|
||||||
case MPElementTypeGeneratedBasic:
|
}
|
||||||
char *ciphers = { "aaanaaan", "aannaaan", "aaannaaa" };
|
case MPElementTypeGeneratedBasic: {
|
||||||
|
char *ciphers[] = { "aaanaaan", "aannaaan", "aaannaaa" };
|
||||||
return ciphers[seedByte % 3];
|
return ciphers[seedByte % 3];
|
||||||
case MPElementTypeGeneratedShort:
|
}
|
||||||
|
case MPElementTypeGeneratedShort: {
|
||||||
return "Cvcn";
|
return "Cvcn";
|
||||||
case MPElementTypeGeneratedPIN:
|
}
|
||||||
|
case MPElementTypeGeneratedPIN: {
|
||||||
return "nnnn";
|
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) {
|
switch (characterClass) {
|
||||||
case 'V':
|
case 'V': {
|
||||||
return "AEIOU"[seedByte];
|
classCharacters = "AEIOU";
|
||||||
case 'C':
|
break;
|
||||||
return "BCDFGHJKLMNPQRSTVWXYZ"[seedByte];
|
}
|
||||||
case 'v':
|
case 'C': {
|
||||||
return "aeiou"[seedByte];
|
classCharacters = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||||
case 'c':
|
break;
|
||||||
return "bcdfghjklmnpqrstvwxyz"[seedByte];
|
}
|
||||||
case 'A':
|
case 'v': {
|
||||||
return "AEIOUBCDFGHJKLMNPQRSTVWXYZ"[seedByte];
|
classCharacters = "aeiou";
|
||||||
case 'a':
|
break;
|
||||||
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"[seedByte];
|
}
|
||||||
case 'n':
|
case 'c': {
|
||||||
return "0123456789"[seedByte];
|
classCharacters = "bcdfghjklmnpqrstvwxyz";
|
||||||
case 'o':
|
break;
|
||||||
return "@&%?,=[]_:-+*$#!'^~;()/."[seedByte];
|
}
|
||||||
case 'x':
|
case 'A': {
|
||||||
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()"[seedByte];
|
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);
|
return classCharacters[seedByte % strlen(classCharacters)];
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,27 +6,27 @@
|
|||||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, MPElementContentType) {
|
typedef enum {
|
||||||
MPElementContentTypePassword,
|
MPElementContentTypePassword,
|
||||||
MPElementContentTypeNote,
|
MPElementContentTypeNote,
|
||||||
MPElementContentTypePicture,
|
MPElementContentTypePicture,
|
||||||
};
|
} MPElementContentType;
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, MPElementTypeClass) {
|
typedef enum {
|
||||||
/** Generate the password. */
|
/** Generate the password. */
|
||||||
MPElementTypeClassGenerated = 1 << 4,
|
MPElementTypeClassGenerated = 1 << 4,
|
||||||
/** Store the password. */
|
/** Store the password. */
|
||||||
MPElementTypeClassStored = 1 << 5,
|
MPElementTypeClassStored = 1 << 5,
|
||||||
};
|
} MPElementTypeClass;
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, MPElementFeature) {
|
typedef enum {
|
||||||
/** Export the key-protected content data. */
|
/** Export the key-protected content data. */
|
||||||
MPElementFeatureExportContent = 1 << 10,
|
MPElementFeatureExportContent = 1 << 10,
|
||||||
/** Never export content. */
|
/** Never export content. */
|
||||||
MPElementFeatureDevicePrivate = 1 << 11,
|
MPElementFeatureDevicePrivate = 1 << 11,
|
||||||
};
|
} MPElementFeature;
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, MPElementType) {
|
typedef enum {
|
||||||
MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
|
MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
|
||||||
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
|
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
|
||||||
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
|
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
|
||||||
@ -36,7 +36,14 @@ typedef NS_ENUM(NSUInteger, MPElementType) {
|
|||||||
|
|
||||||
MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
|
MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
|
||||||
MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
|
MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
|
||||||
};
|
} MPElementType;
|
||||||
|
|
||||||
extern const char *CipherForType(MPElementType type, char seedByte);
|
#ifdef DEBUG
|
||||||
extern const char CharacterFromClass(char characterClass, char seedByte);
|
#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);
|
||||||
|
Loading…
Reference in New Issue
Block a user