2 * $Logfile: /Freespace2/code/parse/Encrypt.cpp $
7 * Module for encryption code common to FreeSpace and related tools
10 * Revision 1.1 2002/05/03 03:28:10 root
14 * 5 4/07/99 5:41p Anoop
15 * Fixed encryption in the launcher.
17 * 4 3/25/99 11:55a Dave
18 * Fixed up encrypt a bit.
20 * 3 3/25/99 11:26a Dave
21 * Beefed up encryption scheme so that even someone viewing the
22 * disassembly would have a hard time cracking it.
24 * 2 10/07/98 10:53a Dave
27 * 1 10/07/98 10:50a Dave
29 * 5 8/09/98 4:44p Lawrance
30 * support alternate encryption scheme (doesn't pack chars into 7 bits)
32 * 4 4/01/98 2:21p Lawrance
33 * check for wacky apostrophe char
35 * 3 3/31/98 4:57p Lawrance
36 * Add signature at the beginning of encrypted files
38 * 2 3/31/98 1:14a Lawrance
39 * Get .tbl and mission file encryption working.
41 * 1 3/30/98 11:02p Lawrance
50 #define ENCRYPT_NEW // new, better encryption scheme
55 const uint Encrypt_new_signature = 0x5c331a55; // new encrpytion
56 const uint Encrypt_signature = 0xdeadbeef; // full encryption
57 const uint Encrypt_signature_8bit = 0xcacacaca; // light encryption - doesn't use 7bit chars
59 int Encrypt_inited = 0;
62 void encrypt_new(char *text, int text_len, char *scrambled_text, int *scrambled_len);
63 void unencrypt_new(char *scrambled_text, int scrambled_len, char *text, int *text_len);
65 // update cur_seed with the chksum of the new_data of size new_data_size
66 ushort chksum_add_short(ushort seed, char *buffer, int size)
68 ubyte * ptr = (ubyte *)buffer;
69 unsigned int sum1,sum2;
71 sum1 = sum2 = (int)(seed);
75 if (sum1 >= 255 ) sum1 -= 255;
80 return (unsigned short)((sum1<<8)+ sum2);
85 // input: text => ascii data to be scrambled
86 // text_len => number of bytes of ascii data to scramble
87 // scrambled_text => storage for scrambled text (malloc at least text_len)
88 // scrambled_len => size of text after getting scrambled
89 // use_8bit => flag to indicate that chars are stored using 8 bits (default value is 0)
90 void encrypt(char *text, int text_len, char *scrambled_text, int *scrambled_len, int use_8bit)
93 encrypt_new(text, text_len, scrambled_text, scrambled_len);
101 // Identify encrypted files with a unique signature
103 memcpy(scrambled_text, &Encrypt_signature_8bit, 4);
105 memcpy(scrambled_text, &Encrypt_signature, 4);
109 // First stage: packing chars into 7 bit boundries
110 for ( i =0; i < text_len; i++ ) {
112 // account for wacky apostrophe that has ascii code 0x92
113 if ( (unsigned char)text[i] == 0x92 ) {
118 scrambled_text[byte_offset++] = text[i];
122 scrambled_text[byte_offset] = (char)((text[i] << 1) & 0xfe);
126 scrambled_text[byte_offset] &= 0x80; // clear out bottom 7 bits
127 scrambled_text[byte_offset] |= (text[i] & 0x7F);
132 scrambled_text[byte_offset] &= 0xc0; // clear out bottom 6 bits
133 scrambled_text[byte_offset] |= ((text[i] >> 1) & 0x3F); // put in top 6 bits
135 scrambled_text[byte_offset] = (char)((text[i] << 7) & 0x80); // put in last bit
139 scrambled_text[byte_offset] &= 0xe0; // clear out bottom 5 bits
140 scrambled_text[byte_offset] |= ((text[i] >> 2) & 0x1F); // put in top 5 bits
142 scrambled_text[byte_offset] = (char)((text[i] << 6) & 0xc0); // put in last two bits
146 scrambled_text[byte_offset] &= 0xf0; // clear out bottom 4 bits
147 scrambled_text[byte_offset] |= ((text[i] >> 3) & 0x0F); // put in top 4 bits
149 scrambled_text[byte_offset] = (char)((text[i] << 5) & 0xe0); // put in last three bits
153 scrambled_text[byte_offset] &= 0xf8; // clear out bottom 3 bits
154 scrambled_text[byte_offset] |= ((text[i] >> 4) & 0x07); // put in top 3 bits
156 scrambled_text[byte_offset] = (char)((text[i] << 4) & 0xf0); // put in last four bits
160 scrambled_text[byte_offset] &= 0xfc; // clear out bottom 2 bits
161 scrambled_text[byte_offset] |= ((text[i] >> 5) & 0x03); // put in top 2 bits
163 scrambled_text[byte_offset] = (char)((text[i] << 3) & 0xf8); // put in last five bits
167 scrambled_text[byte_offset] &= 0xfe; // clear out bottom bit
168 scrambled_text[byte_offset] |= ((text[i] >> 6) & 0x01); // put in top bit
170 scrambled_text[byte_offset] = (char)((text[i] << 2) & 0xfc); // put in last six bits
179 if ( bit_offset > 0 ) {
183 *scrambled_len = byte_offset;
185 // Second stage: XOR with offset into file (skip signature)
187 int len = *scrambled_len - 4;
188 for ( i =0; i < len; i++ ) {
189 scrambled_text[i] ^= i;
194 // input: scrambled_text => scrambled text
195 // scrambled_len => number of bytes of scrambled text
196 // text => storage for unscrambled ascii data
197 // text_len => actual number of bytes of unscrambled data
198 void unencrypt(char *scrambled_text, int scrambled_len, char *text, int *text_len)
201 unencrypt_new(scrambled_text, scrambled_len, text, text_len);
204 int scramble_offset = 0;
210 // Only decrpyt files that start with unique signature
211 memcpy(&encrypt_id, scrambled_text, 4);
213 if ( (encrypt_id != Encrypt_signature) && (encrypt_id != Encrypt_signature_8bit) ) {
214 memcpy(text, scrambled_text, scrambled_len);
215 *text_len = scrambled_len;
222 // First decrypt stage: undo XOR operation
223 for ( i =0; i < scrambled_len; i++ ) {
224 scrambled_text[i] ^= i;
227 if (encrypt_id == Encrypt_signature_8bit) {
228 memcpy(text, scrambled_text, scrambled_len);
229 *text_len = scrambled_len;
233 // Second decrypt stage: remove chars from 7 bit packing to 8 bit boundries
234 num_runs = (int) (scrambled_len / 7.0f );
235 if ( scrambled_len % 7 ) {
239 for ( i =0; i < num_runs; i++ ) {
240 // a run consists of 8 chars packed into 56 bits (instead of 64)
242 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 1) & 0x7f);
246 if ( scramble_offset >= scrambled_len ) {
250 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 2) & 0x3f);
251 text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 6) & 0x40 );
255 if ( scramble_offset >= scrambled_len ) {
259 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 3) & 0x1f);
260 text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 5) & 0x60 );
264 if ( scramble_offset >= scrambled_len ) {
268 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 4) & 0x0f);
269 text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 4) & 0x70 );
273 if ( scramble_offset >= scrambled_len ) {
277 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 5) & 0x07);
278 text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 3) & 0x78 );
282 if ( scramble_offset >= scrambled_len ) {
286 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 6) & 0x03);
287 text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 2) & 0x7c );
291 if ( scramble_offset >= scrambled_len ) {
295 text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 7) & 0x01);
296 text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 1) & 0x7e );
299 maybe_last = (char)(scrambled_text[scramble_offset] & 0x7f);
300 if ( maybe_last > 0 ) {
301 text[byte_offset] = maybe_last;
307 *text_len = byte_offset;
311 #define NUM_LVL1_KEYS 11
312 ushort Lvl1_keys[NUM_LVL1_KEYS] = {
321 // scramble text data
323 // input: text => ascii data to be scrambled
324 // text_len => number of bytes of ascii data to scramble
325 // scrambled_text => storage for scrambled text (malloc at least text_len)
326 // scrambled_len => size of text after getting scrambled
327 void encrypt_new(char *text, int text_len, char *scrambled_text, int *scrambled_len)
329 ushort lvl1_block[NUM_LVL1_KEYS * 2];
330 ushort block_checksum;
333 // add the encrpytion signature
334 memcpy(scrambled_text, &Encrypt_new_signature, 4);
336 // go through and read in chunks of NUM_LVL1_KEYS * 2 bytes
337 block_checksum = 0xffff;
339 while(*scrambled_len < text_len){
340 // if we have less than one block left
341 if((text_len - *scrambled_len) < (NUM_LVL1_KEYS * 2)){
342 memcpy(lvl1_block, text + *scrambled_len, text_len - *scrambled_len);
343 block_size = text_len - *scrambled_len;
345 // if we have at least one full block left
347 memcpy(lvl1_block, text + *scrambled_len, NUM_LVL1_KEYS * 2);
348 block_size = NUM_LVL1_KEYS * 2;
351 // run the lvl1 over the block
352 for(idx=0; idx<block_size/2; idx++){
353 // the base key with the running checksum from the _last_ block
354 lvl1_block[idx] ^= (Lvl1_keys[idx] ^ block_checksum);
357 // the running checksum
358 block_checksum = chksum_add_short(block_checksum, (char*)lvl1_block, block_size);
360 // copy into the outgoing buffer
361 memcpy(scrambled_text + *scrambled_len + 4, lvl1_block, block_size);
362 *scrambled_len += block_size;
365 // add the 4 bytes for the header
370 // input: scrambled_text => scrambled text
371 // scrambled_len => number of bytes of scrambled text
372 // text => storage for unscrambled ascii data
373 // text_len => actual number of bytes of unscrambled data
374 void unencrypt_new(char *scrambled_text, int scrambled_len, char *text, int *text_len)
376 ushort lvl1_block[NUM_LVL1_KEYS * 2];
377 ushort lvl1_block_copy[NUM_LVL1_KEYS * 2];
378 ushort block_checksum;
382 // Only decrypt files that start with unique signature
383 memcpy(&encrypt_id, scrambled_text, 4);
384 if (encrypt_id != Encrypt_new_signature) {
385 memcpy(text, scrambled_text, scrambled_len);
386 *text_len = scrambled_len;
390 // go through and read in chunks of NUM_LVL1_KEYS * 2 bytes
394 block_checksum = 0xffff;
395 while(*text_len < scrambled_len){
396 // if we have less than one block left
397 if((scrambled_len - *text_len) < (NUM_LVL1_KEYS * 2)){
398 memcpy(lvl1_block, scrambled_text + *text_len, scrambled_len - *text_len);
399 block_size = scrambled_len - *text_len;
401 // if we have at least one full block left
403 memcpy(lvl1_block, scrambled_text + *text_len, NUM_LVL1_KEYS * 2);
404 block_size = NUM_LVL1_KEYS * 2;
407 // copy the block so that we can properly calculate the next running checksum
408 memcpy(lvl1_block_copy, lvl1_block, block_size);
409 // run the lvl1 over the block
410 for(idx=0; idx<block_size/2; idx++){
411 lvl1_block[idx] ^= (Lvl1_keys[idx] ^ block_checksum);
414 // the running checksum
415 block_checksum = chksum_add_short(block_checksum, (char*)lvl1_block_copy, block_size);
417 // copy into the outgoing buffer
418 memcpy(text + *text_len, lvl1_block, block_size);
419 *text_len += block_size;
423 // Return 1 if the data is encrypted, otherwise return 0
424 int is_encrpyted(char *scrambled_text)
428 memcpy(&encrypt_id, scrambled_text, 4);
430 if ( (encrypt_id == Encrypt_signature) || (encrypt_id == Encrypt_signature_8bit) || (encrypt_id == Encrypt_new_signature)) {
437 // initialize encryption
441 ushort haha_you_dumbass = 0xe2A8;
447 // meddle with the key table so someone reading the disassembly won't be able to get key values unless they're _REALLY_ careful
448 for(idx=0; idx<NUM_LVL1_KEYS; idx++){
449 Lvl1_keys[idx] ^= (haha_you_dumbass >> 2);