[EMAIL PROTECTED] wrote:
Thanks for the tips.
I see his code uses __attribute__((packed)) for some of the data
structures.
Did you replace this with #pragma options align=packed before the packed
structure defines and #pragma options align=native after the packed structures ?
I remember that I had problems with this guy, here follows the solution
how it is working now:
typedef struct tagHashingBlock
{
char acUserName_[32] __attribute__ ((packed));
unsigned long nSalt_:32 __attribute__ ((packed));
unsigned int nSerialNumber_:16 __attribute__ ((packed));
unsigned int nVersion_:8 __attribute__ ((packed)) ;
} HashingBlock;
//#pragma options align= packed
typedef struct tagKeyBlock
{
unsigned int nSerialNumber_:16 __attribute__ ((packed));
unsigned int nVersion_:8 __attribute__ ((packed));
unsigned long nHash_:32 __attribute__ ((packed));
} KeyBlock;
//#pragma options align= packed
the #pragma is commented out.
i remember that CW understand this struct size differently leading to
that problems that it increase the struct size. This will lead that your
final register code will increase in one character, so it will change
from XXXX-YYYY-ZZZZ to W-XXXX-YYYY-ZZZZ
if you don't like the format you can change the it latter (lets discuss
it when you have the basic working)
Regarding Keytool.cpp, you need a lot of changes, here follows the code:
/***********************************************************************
keytool.cpp - A tool to generate and verify Tangentsoft Palm OS
Registration Tools (PORT) keys.
Inputs:
User name (a.k.a. Palm device name, first 31 characters)
Serial number (16 bits)
Key format version (8 bits)
Seasoning:
32 bits magic salt
32 bits hash of all the above
Output:
56 bit key, expressed in base-32 notation (0-9A-Z, excepting 0,
1, I and O), composed of the 16 bit serial number, 8 bit
program version, and the 32 bit hash. (Encoded output
is
12 base-32 digits, displayed in 3 groups of 4 digits.)
Created 2000.09.24 by Warren Young
$Date: 2005/07/13 14:48:14 $ $Revision: 1.5 $
Copyright (c) 1999-2003 by Warren Young. This program is hereby
released under the GNU General Public License, a copy of which is in
the file COPYING, which should have accompanied this program.
***********************************************************************/
#include "keyutility.h"
#include "crc_32.h"
#include "private.h"
#include <sys/stat.h>
#ifdef __MWERKS__
#include <time.h>
#include "getopt.c"
#else
#include <sys/time.h>
#include <getopt.h>
#endif
#include <errno.h>
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <time.h>
#ifdef __MWERKS__
// #include <netmgr.h>
#else
#include <netinet/in.h> // for htons() and friends
#endif
using namespace std;
//general compatibility
#if CPU_TYPE == CPU_x86
#define _NetSwap16(x) \
((((x) >> 8) & 0xFF) | \
(((x) & 0xFF) << 8))
#define _NetSwap32(x) \
((((x) >> 24) & 0x00FF) | \
(((x) >> 8) & 0xFF00) | \
(((x) & 0xFF00) << 8) | \
(((x) & 0x00FF) << 24))
#define NetHToNS(x) _NetSwap16(x)
#define NetHToNL(x) _NetSwap32(x)
#define NetNToHS(x) _NetSwap16(x)
#define NetNToHL(x) _NetSwap32(x)
#elif CPU_TYPE == CPU_68K
#define NetHToNS(x) (x)
#define NetHToNL(x) (x)
#define NetNToHS(x) (x)
#define NetNToHL(x) (x)
#endif
////////////////////////////////////////////////////////////////////////
// Constants
static const char* kpcSerialFile = "last-serial.txt";
static const char* kpcLicenseLogFile = "license-log.txt";
//// GetNextSerial /////////////////////////////////////////////////////
// Load the previous serial number (if any) and increase it by a
// predefined value, to get the next serial number. Return it if all
// this is successful; else return -1.
static int GetNextSerial()
{
// Is serial number file here? If so, load in the last key number
// and bump it. If not, set key number to default value.
struct stat FileInfo;
if (stat(kpcSerialFile, &FileInfo) == -1) {
if (errno == ENOENT) {
cout << "WARNING: last serial number not found; starting
"
"over." << endl;
return PORT_FIRST_SERIAL;
}
else {
perror("Could not stat serial number file");
return -1;
}
}
else {
// Read last serial from file and add a prime number to it.
// (The "stride.") This should ensure that we cover all the
// serial number values, if we wrap through the data set enough.
// More importantly, we should never duplicate a serial number
// until we've gone through the entire set.
ifstream ifs(kpcSerialFile);
char ac[20];
unsigned int nOldSerial, nNewSerial;
ifs.getline(ac, sizeof(ac));
nOldSerial = atoi(ac);
nNewSerial = nOldSerial + PORT_STRIDE;
if (nNewSerial > nOldSerial) {
return nNewSerial;
}
else {
cerr << "Serial number wrapped around. You must change the
"
"start serial number" << endl;
cerr << "before the program can continue to make keys."
<<
endl;
return -1;
}
}
}
//// CreateNewKey //////////////////////////////////////////////////////
// Given a user name, generate a new key.
static int
CreateNewKey(const char* pcUserName, const char* pcOrder)
{
KeyBlock key;
memset(&key, 0, sizeof(key));
// Put the next legal serial number into the key.
int nNextSerial = GetNextSerial();
if (nNextSerial > 0) {
key.nSerialNumber_ = NetHToNS(nNextSerial);
}
else {
return 1;
}
// Set up the key and create the hash for it
key.nVersion_ = PORT_VERSION;
key.nHash_ = NetHToNL(HashKey(&key, pcUserName));
// Generate base 32 version of key block.
char acTempKey[40], acKey[60], acInfo[200];
memset(acTempKey, 0, sizeof(acTempKey));
BlindKey(&key);
ConvertToBase32(acTempKey, (char*)&key, sizeof(key));
MakeBase32Pretty(acKey, acTempKey);
BlindKey(&key);
// Write results out to the license log and to the screen, in a kind
// of CSV-like format.
time_t Now = time(0);
struct tm* pNowTM = localtime(&Now);
snprintf(acInfo, sizeof(acInfo), "%d,%d,%s,%s,%s,%04d/%02d/%02d",
nNextSerial, PORT_VERSION, pcUserName, acKey, pcOrder,
pNowTM->tm_year + 1900, pNowTM->tm_mon + 1,
pNowTM->tm_mday);
puts(acInfo);
ofstream ofs(kpcLicenseLogFile, ios::app);
if (ofs) {
ofs << acInfo << endl;
}
// Write serial number out to file, so we can pick up with next
// serial number next time.
ofs.close();
ofs.open(kpcSerialFile);
if (ofs) {
ofs << nNextSerial << endl;
}
return 0;
}
//// VerifyKey //////////////////////////////////////////////////////
// Given a base 32-encoded key, verify that it's not been tampered
// with and that the key belongs to the named user.
static int
VerifyKey(const char* pcKey, const char* pcUserName)
{
KeyBlock key;
memset(&key, 0, sizeof(key));
// Unencode and un-blind the key
char acCleanedKey[30];
memset(acCleanedKey, 0, sizeof(acCleanedKey));
CleanForBase32(acCleanedKey, pcKey);
int nBadChar = ConvertFromBase32((char*)&key, acCleanedKey,
strlen(acCleanedKey));
if (nBadChar != 0) {
cerr << "Error, character '" << char(nBadChar) << "' (" <<
nBadChar << ") in key!" << endl;
return 1;
}
BlindKey(&key);
// Write out the contents of the decoded key.
cout << "Key " << acCleanedKey << " claims to be serial number " <<
NetHToNS(key.nSerialNumber_);
cout << ", version " << key.nVersion_ << ", hash " <<
NetNToHL(key.nHash_) << "." << endl;
// Check the serial number for validity.
int nSerialNumber = NetNToHS(key.nSerialNumber_);
nSerialNumber -= PORT_FIRST_SERIAL;
if ((nSerialNumber % PORT_STRIDE) == 0) {
cout << "Serial number appears to be valid." << endl;
}
else {
cerr << "Serial number is NOT VALID for the series starting " <<
PORT_FIRST_SERIAL << " with stride " << PORT_STRIDE
<<
"." << endl;
return 1;
}
// Re-encode the key to see if the calculated hash matches the
// claimed hash, given the user name and the other data in the key.
unsigned long nCalcHash = HashKey(&key, pcUserName);
if (nCalcHash == NetNToHL(key.nHash_)) {
cout << "This key appears to be valid." << endl;
cout << endl;
return 0;
}
else {
cerr << "This key appears have been TAMPERED with." << endl;
cerr << "The hash should be " << nCalcHash <<
", given this data." << endl;
cerr << endl;
return 1;
}
}
//// usage /////////////////////////////////////////////////////////////
// Display the usage message
static void
usage()
{
cerr << endl;
cerr << "usage: keytool -u username [-k key]\n";
cerr << endl;
cerr << " -u\tPalm user name\n";
cerr << " -k\tKey generated by keytool, in base 32 format\n";
cerr << " -o\tOrder number, stored in the log for info purposes\n";
cerr << endl;
cerr << " If -k is not given, a new key is generated for
username.\n";
cerr << " If -k is given, the key is checked for tampering and\n";
cerr << " checked to see if it belongs to username.\n";
cerr << endl;
}
//// main //////////////////////////////////////////////////////////////
//#include <console.h>
int
main(int argc, char* argv[])
{
const char* pcKey = 0;
const char* pcOrder = "unknown";
const char* pcUserName = 0;
#ifdef __MWERKS__
#endif //__MWERKS__
// Parse the command line
int ch;
while ((ch = getopt(argc, argv, "k:o:u:")) != EOF) {
switch (ch) {
case 'k':
pcKey = optarg;
break;
case 'o':
pcOrder = optarg;
break;
case 'u':
pcUserName = optarg;
break;
case '?':
default:
usage();
return 1;
}
}
if (pcUserName == 0) {
usage();
return 1;
}
if (pcKey == 0) {
return CreateNewKey(pcUserName, pcOrder);
}
else {
return VerifyKey(pcKey, pcUserName);
}
}
the main changes are regarding htons functions for example that are
replaced by NetHToNS for example and some headers replaced.
Instead of change the htons functions here, you can change it also
change it on compat.h (compatibility header) that is the correct way to
do it. We just figure out it after done it.
you could add something like:
//compat.h
#ifdef __MWERKS__
#define HTONS NetHToNS
#endif
hope this helps for while.
regards
Erico Franco
MicroMagic
--
For information on using the PalmSource Developer Forums, or to unsubscribe,
please see http://www.palmos.com/dev/support/forums/