[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/

Reply via email to