Stadin, Benjamin wrote:
> I've chosen XXTEA (not XTEA but a derivate) for encryption and decryption
>
> On the Palm side I use the code below to decrypt the text. My problem is
> that I'm not able to decrypt the text on my Palm. The decryption function
> reads beyond the data or starts at an odd address.
Some processors let you read unaligned values and some do not.
In other words, some processors have no restrictions, but on
other processors, any time you read a 16-bit quantity from a
pointer, that pointer must point to an even memory address,
and any time you read a 32-bit quantity from a pointer, that
pointer must point to an address that is a multiple of 4.
(This way, reading a 32-bit quantity with a 32-bit bus is
much simple and much faster since you only need to read from
memory one time.)
On the Palm, there are alignment restrictions. I believe it
is only 2-byte alignment for 68k but it is 4-byte alignment
for ARM.
> // That's what I use before calling the decryption function:
> memoRecP = MemHandleLock (memoRecH);
Here, memoRecP should be properly aligned because MemHandleLock()
should guarantee that.
> noteLength = memoRecP->noteLength;
> note = &memoRecP->keyn +4;
The variable "note" may or may not be properly aligned. It
depends on the offset of keyn within the record.
> note += StrLen (note) + 1;
At this point, assuming "note" is a pointer to a 1-byte
quantity (UInt8, Char, etc.), the pointer is likely to be
unaligned. It will only be aligned if StrLen(note) is a
3, 7, 11, 15, ... (some number such that StrLen(note) % 4 == 3).
> offset = note - (Char*)memoRecP;
This statement seems unnecessary, at least for this example. :-)
> btea((long *) note, -32, (long *) key); // <-- decrypt the note
Here you are casting "note" as a "long *". But since it could
be on any alignment, when you dereference that pointer, you have
a 3/4 chance (depending on StrLen(note)) of causing the processor
to try to read from an address that is not a multiple of 4, which
will cause big problems, as you have already noticed.
There are two solutions:
(1) Rewrite the function so that it can deal with data on
any alignment. You will have to read and write a byte
at a time. For example, to get a 32-bit quantity from
"note" (which I would leave as a UInt8 pointer), you
need to do something like this:
z = note[0]
z <<= 8;
z |= note[1];
z <<= 8;
z |= note[2];
z <<= 8;
z |= note[3];
Note that this reads in big-endian, but if you are creating
data on an x86 system, that might write in little endian,
so you need to make a decision about which format to use
and if you choose little-endian, you will have to read the
bytes in the opposite order. (Also note that if you try
to combine those 7 statements into one, be careful to cast
the values to 32-bit integers before you shift them, or
otherwise you will be shifting an 8-bit integer by 8 or
more and thereby getting a zero as the result!)
(2) Make sure that "note" points to memory which is 32-bit
aligned:
Int32 *alignednote = (Int32 *) MemPtrNew (StrLen(note) + 1 + 3);
MemMove (alignednote, note, StrLen(note) + 1);
I am adding 3 to be sure that "alignednote" always contains
a full 32-bit quantity. You don't want to have the string
"abcde" and then only allocate 6 bytes but then try to
read 8 byte by reading 2 32-bit words.
Hope that helps.
- Logan
--
For information on using the Palm Developer Forums, or to unsubscribe, please
see http://www.palmos.com/dev/support/forums/