FS2_Open
Open source remastering of the Freespace 2 engine
encrypt.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #define ENCRYPT_NEW // new, better encryption scheme
17 
18 #include "globalincs/pstypes.h"
19 #include "parse/encrypt.h"
20 
21 
22 
23 #if BYTE_ORDER == BIG_ENDIAN
24 const uint Encrypt_new_signature = 0x551a335c; // new encrpytion
25 const uint Encrypt_signature = 0xefbeadde; // full encryption
26 #else
27 const uint Encrypt_new_signature = 0x5c331a55; // new encryption
28 const uint Encrypt_signature = 0xdeadbeef; // full encryption
29 #endif
30 const uint Encrypt_signature_8bit = 0xcacacaca; // light encryption - doesn't use 7bit chars
31 
33 
34 // new encryption
35 void encrypt_new(char *text, int text_len, char *scrambled_text, int *scrambled_len);
36 void unencrypt_new(char *scrambled_text, int scrambled_len, char *text, int *text_len);
37 
38 // update cur_seed with the chksum of the new_data of size new_data_size
40 {
41  ubyte * ptr = (ubyte *)buffer;
42  unsigned int sum1,sum2;
43 
44  sum1 = sum2 = (int)(seed);
45 
46  while(size--) {
47  sum1 += *ptr++;
48  if (sum1 >= 255 ) sum1 -= 255;
49  sum2 += sum1;
50  }
51  sum2 %= 255;
52 
53  return (unsigned short)((sum1<<8)+ sum2);
54 }
55 
56 // scramble text data
57 //
58 // input: text => ascii data to be scrambled
59 // text_len => number of bytes of ascii data to scramble
60 // scrambled_text => storage for scrambled text (malloc at least text_len)
61 // scrambled_len => size of text after getting scrambled
62 // use_8bit => flag to indicate that chars are stored using 8 bits (default value is 0)
63 // new_encrypt => flag to switch between old and new encryption styles (default = yes)
64 void encrypt(char *text, int text_len, char *scrambled_text, int *scrambled_len, int use_8bit, bool new_encrypt)
65 {
66 #ifdef ENCRYPT_NEW
67  // new_encrypt, when set, is for FS2 style encryption
68  // when not set it's either of two FS1 styles, 8bit or 7bit
69  if (new_encrypt == true) {
70  encrypt_new(text, text_len, scrambled_text, scrambled_len);
71  return;
72  }
73 #endif
74 
75  int i;
76  int byte_offset = 0;
77  int bit_offset = 0;
78 
79  *scrambled_len = 0;
80 
81  // Identify encrypted files with a unique signature
82  if (use_8bit) {
83  memcpy(scrambled_text, &Encrypt_signature_8bit, 4);
84  } else {
85  memcpy(scrambled_text, &Encrypt_signature, 4);
86  }
87  byte_offset = 4;
88 
89  // First stage: packing chars into 7 bit boundries
90  for ( i =0; i < text_len; i++ ) {
91 
92  // account for wacky apostrophe that has ascii code 0x92
93  if ( (unsigned char)text[i] == 0x92 ) {
94  text[i] = 0x27;
95  }
96 
97  if (use_8bit) {
98  scrambled_text[byte_offset++] = text[i];
99  } else {
100  switch(bit_offset) {
101  case 0:
102  scrambled_text[byte_offset] = (char)((text[i] << 1) & 0xfe);
103  bit_offset = 7;
104  break;
105  case 1:
106  scrambled_text[byte_offset] &= 0x80; // clear out bottom 7 bits
107  scrambled_text[byte_offset] |= (text[i] & 0x7F);
108  byte_offset++;
109  bit_offset = 0;
110  break;
111  case 2:
112  scrambled_text[byte_offset] &= 0xc0; // clear out bottom 6 bits
113  scrambled_text[byte_offset] |= ((text[i] >> 1) & 0x3F); // put in top 6 bits
114  byte_offset++;
115  scrambled_text[byte_offset] = (char)((text[i] << 7) & 0x80); // put in last bit
116  bit_offset = 1;
117  break;
118  case 3:
119  scrambled_text[byte_offset] &= 0xe0; // clear out bottom 5 bits
120  scrambled_text[byte_offset] |= ((text[i] >> 2) & 0x1F); // put in top 5 bits
121  byte_offset++;
122  scrambled_text[byte_offset] = (char)((text[i] << 6) & 0xc0); // put in last two bits
123  bit_offset = 2;
124  break;
125  case 4:
126  scrambled_text[byte_offset] &= 0xf0; // clear out bottom 4 bits
127  scrambled_text[byte_offset] |= ((text[i] >> 3) & 0x0F); // put in top 4 bits
128  byte_offset++;
129  scrambled_text[byte_offset] = (char)((text[i] << 5) & 0xe0); // put in last three bits
130  bit_offset = 3;
131  break;
132  case 5:
133  scrambled_text[byte_offset] &= 0xf8; // clear out bottom 3 bits
134  scrambled_text[byte_offset] |= ((text[i] >> 4) & 0x07); // put in top 3 bits
135  byte_offset++;
136  scrambled_text[byte_offset] = (char)((text[i] << 4) & 0xf0); // put in last four bits
137  bit_offset = 4;
138  break;
139  case 6:
140  scrambled_text[byte_offset] &= 0xfc; // clear out bottom 2 bits
141  scrambled_text[byte_offset] |= ((text[i] >> 5) & 0x03); // put in top 2 bits
142  byte_offset++;
143  scrambled_text[byte_offset] = (char)((text[i] << 3) & 0xf8); // put in last five bits
144  bit_offset = 5;
145  break;
146  case 7:
147  scrambled_text[byte_offset] &= 0xfe; // clear out bottom bit
148  scrambled_text[byte_offset] |= ((text[i] >> 6) & 0x01); // put in top bit
149  byte_offset++;
150  scrambled_text[byte_offset] = (char)((text[i] << 2) & 0xfc); // put in last six bits
151  bit_offset = 6;
152  break;
153  default:
154  return;
155  }
156  }
157  }
158 
159  if ( bit_offset > 0 ) {
160  byte_offset++;
161  }
162 
163  *scrambled_len = byte_offset;
164 
165  // Second stage: XOR with offset into file (skip signature)
166  scrambled_text += 4;
167  int len = *scrambled_len - 4;
168  for ( i =0; i < len; i++ ) {
169  scrambled_text[i] ^= i;
170  }
171 }
172 
173 // input: scrambled_text => scrambled text
174 // scrambled_len => number of bytes of scrambled text
175 // text => storage for unscrambled ascii data
176 // text_len => actual number of bytes of unscrambled data
177 void unencrypt(char *scrambled_text, int scrambled_len, char *text, int *text_len)
178 {
179 #ifdef ENCRYPT_NEW
180  // check if we are an old FS1 style encryption before moving to new type
181  if ( !is_old_encrypt(scrambled_text) ) {
182  unencrypt_new(scrambled_text, scrambled_len, text, text_len);
183  return;
184  }
185 #endif
186 
187  int i, num_runs;
188  int scramble_offset = 0;
189  int byte_offset = 0;
190  char maybe_last = 0;
191 
192  uint encrypt_id;
193 
194  // Only decrypt files that start with unique signature
195  memcpy(&encrypt_id, scrambled_text, 4);
196 
197  if ( (encrypt_id != Encrypt_signature) && (encrypt_id != Encrypt_signature_8bit) ) {
198  memcpy(text, scrambled_text, scrambled_len);
199  *text_len = scrambled_len;
200  return;
201  }
202 
203  scrambled_text += 4;
204  scrambled_len -= 4;
205 
206  // First decrypt stage: undo XOR operation
207  for ( i =0; i < scrambled_len; i++ ) {
208  scrambled_text[i] ^= i;
209  }
210 
211  if (encrypt_id == Encrypt_signature_8bit) {
212  memcpy(text, scrambled_text, scrambled_len);
213  *text_len = scrambled_len;
214  return;
215  }
216 
217  // Second decrypt stage: remove chars from 7 bit packing to 8 bit boundries
218  num_runs = (int) (scrambled_len / 7.0f );
219  if ( scrambled_len % 7 ) {
220  num_runs++;
221  }
222 
223  for ( i =0; i < num_runs; i++ ) {
224  // a run consists of 8 chars packed into 56 bits (instead of 64)
225 
226  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 1) & 0x7f);
227  byte_offset++;
228  scramble_offset++;
229 
230  if ( scramble_offset >= scrambled_len ) {
231  break;
232  }
233 
234  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 2) & 0x3f);
235  text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 6) & 0x40 );
236  byte_offset++;
237  scramble_offset++;
238 
239  if ( scramble_offset >= scrambled_len ) {
240  break;
241  }
242 
243  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 3) & 0x1f);
244  text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 5) & 0x60 );
245  byte_offset++;
246  scramble_offset++;
247 
248  if ( scramble_offset >= scrambled_len ) {
249  break;
250  }
251 
252  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 4) & 0x0f);
253  text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 4) & 0x70 );
254  byte_offset++;
255  scramble_offset++;
256 
257  if ( scramble_offset >= scrambled_len ) {
258  break;
259  }
260 
261  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 5) & 0x07);
262  text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 3) & 0x78 );
263  byte_offset++;
264  scramble_offset++;
265 
266  if ( scramble_offset >= scrambled_len ) {
267  break;
268  }
269 
270  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 6) & 0x03);
271  text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 2) & 0x7c );
272  byte_offset++;
273  scramble_offset++;
274 
275  if ( scramble_offset >= scrambled_len ) {
276  break;
277  }
278 
279  text[byte_offset] = (char)((scrambled_text[scramble_offset] >> 7) & 0x01);
280  text[byte_offset] |= ( (scrambled_text[scramble_offset-1] << 1) & 0x7e );
281  byte_offset++;
282 
283  maybe_last = (char)(scrambled_text[scramble_offset] & 0x7f);
284  if ( maybe_last > 0 ) {
285  text[byte_offset] = maybe_last;
286  byte_offset++;
287  scramble_offset++;
288  }
289  }
290 
291  *text_len = byte_offset;
292 }
293 
294 #define NUM_LVL1_KEYS 11
296  0xa820, 0x71f0,
297  0x88da, 0x1fff,
298  0x2718, 0xe6a1,
299  0x42b8, 0x0ce9,
300  0x10ec, 0xd77d,
301  0x3fa9
302 };
303 
304 // scramble text data
305 //
306 // input: text => ascii data to be scrambled
307 // text_len => number of bytes of ascii data to scramble
308 // scrambled_text => storage for scrambled text (malloc at least text_len)
309 // scrambled_len => size of text after getting scrambled
310 void encrypt_new(char *text, int text_len, char *scrambled_text, int *scrambled_len)
311 {
312  ushort lvl1_block[NUM_LVL1_KEYS * 2];
313  ushort block_checksum;
314  int block_size, idx;
315 
316  // add the encryption signature
317  memcpy(scrambled_text, &Encrypt_new_signature, 4);
318 
319  // go through and read in chunks of NUM_LVL1_KEYS * 2 bytes
320  block_checksum = 0xffff;
321  *scrambled_len = 0;
322  while(*scrambled_len < text_len){
323  // if we have less than one block left
324  if((text_len - *scrambled_len) < (NUM_LVL1_KEYS * 2)){
325  memcpy(lvl1_block, text + *scrambled_len, text_len - *scrambled_len);
326  block_size = text_len - *scrambled_len;
327  }
328  // if we have at least one full block left
329  else {
330  memcpy(lvl1_block, text + *scrambled_len, NUM_LVL1_KEYS * 2); //-V512
331  block_size = NUM_LVL1_KEYS * 2;
332  }
333 
334  // run the lvl1 over the block
335  for(idx=0; idx<block_size/2; idx++){
336  // the base key with the running checksum from the _last_ block
337  lvl1_block[idx] ^= (Lvl1_keys[idx] ^ block_checksum);
338  }
339 
340  // the running checksum
341  block_checksum = chksum_add_short(block_checksum, (char*)lvl1_block, block_size);
342 
343  // copy into the outgoing buffer
344  memcpy(scrambled_text + *scrambled_len + 4, lvl1_block, block_size);
345  *scrambled_len += block_size;
346  }
347 
348  // add the 4 bytes for the header
349  *scrambled_len += 4;
350 
351 }
352 
353 // input: scrambled_text => scrambled text
354 // scrambled_len => number of bytes of scrambled text
355 // text => storage for unscrambled ascii data
356 // text_len => actual number of bytes of unscrambled data
357 void unencrypt_new(char *scrambled_text, int scrambled_len, char *text, int *text_len)
358 {
359  ushort lvl1_block[NUM_LVL1_KEYS * 2];
360  ushort lvl1_block_copy[NUM_LVL1_KEYS * 2];
361  ushort block_checksum;
362  int block_size, idx;
363  uint encrypt_id;
364 
365  // Only decrypt files that start with unique signature
366  memcpy(&encrypt_id, scrambled_text, 4);
367  if (encrypt_id != Encrypt_new_signature) {
368  memcpy(text, scrambled_text, scrambled_len);
369  *text_len = scrambled_len;
370  return;
371  }
372 
373  // go through and read in chunks of NUM_LVL1_KEYS * 2 bytes
374  *text_len = 0;
375  scrambled_text += 4;
376  scrambled_len -= 4;
377  block_checksum = 0xffff;
378  while(*text_len < scrambled_len){
379  // if we have less than one block left
380  if((scrambled_len - *text_len) < (NUM_LVL1_KEYS * 2)){
381  memcpy(lvl1_block, scrambled_text + *text_len, scrambled_len - *text_len);
382  block_size = scrambled_len - *text_len;
383  }
384  // if we have at least one full block left
385  else {
386  memcpy(lvl1_block, scrambled_text + *text_len, NUM_LVL1_KEYS * 2); //-V512
387  block_size = NUM_LVL1_KEYS * 2;
388  }
389 
390  // copy the block so that we can properly calculate the next running checksum
391  memcpy(lvl1_block_copy, lvl1_block, block_size);
392  // run the lvl1 over the block
393  for(idx=0; idx<block_size/2; idx++){
394  lvl1_block[idx] ^= (Lvl1_keys[idx] ^ block_checksum);
395  }
396 
397  // the running checksum
398  block_checksum = chksum_add_short(block_checksum, (char*)lvl1_block_copy, block_size);
399 
400  // copy into the outgoing buffer
401  memcpy(text + *text_len, lvl1_block, block_size);
402  *text_len += block_size;
403  }
404 }
405 
406 // Return 1 if the data is encrypted, otherwise return 0
407 int is_encrypted(char *scrambled_text)
408 {
409  uint encrypt_id;
410 
411  memcpy(&encrypt_id, scrambled_text, 4);
412 
413  if ( (encrypt_id == Encrypt_signature) || (encrypt_id == Encrypt_signature_8bit) || (encrypt_id == Encrypt_new_signature)) {
414  return 1;
415  }
416 
417  return 0;
418 }
419 
420 // Returns 1 if the data uses a FS1 style encryption, 0 if FS2 style
421 int is_old_encrypt(char *scrambled_text)
422 {
423  uint encrypt_id;
424 
425  memcpy(&encrypt_id, scrambled_text, 4);
426 
427  if ( (encrypt_id == Encrypt_signature) || (encrypt_id == Encrypt_signature_8bit) ) {
428  return 1;
429  }
430 
431  return 0;
432 }
433 
434 // return text description of the encrypted text type
435 const char *encrypt_type(char *scrambled_text)
436 {
437  uint encrypt_id;
438 
439  memcpy(&encrypt_id, scrambled_text, 4);
440 
441  if (encrypt_id == Encrypt_signature) {
442  return "FreeSpace 1 type encryption, 7-bit";
443  } else if (encrypt_id == Encrypt_signature_8bit) {
444  return "FreeSpace 1 type encryption, 8-bit";
445  } else if (encrypt_id == Encrypt_new_signature) {
446  return "FreeSpace 2 type encryption";
447  } else {
448  return "Not encrypted or unknown encryption type";
449  }
450 }
451 
452 // initialize encryption
454 {
455  int idx;
456  ushort temp_var = 0xe2A8;
457 
458  if(Encrypt_inited){
459  return;
460  }
461 
462  // meddle with the key table so someone reading the disassembly won't be able to get key values unless they're _REALLY_ careful
463  for(idx=0; idx<NUM_LVL1_KEYS; idx++){
464  Lvl1_keys[idx] ^= (temp_var >> 2);
465  }
466 
467  Encrypt_inited = 1;
468 }
int i
Definition: multi_pxo.cpp:466
ushort chksum_add_short(ushort seed, char *buffer, int size)
Definition: encrypt.cpp:39
void unencrypt(char *scrambled_text, int scrambled_len, char *text, int *text_len)
Definition: encrypt.cpp:177
void unencrypt_new(char *scrambled_text, int scrambled_len, char *text, int *text_len)
Definition: encrypt.cpp:357
const uint Encrypt_signature
Definition: encrypt.cpp:25
const uint Encrypt_new_signature
Definition: encrypt.cpp:24
const uint Encrypt_signature_8bit
Definition: encrypt.cpp:30
GLclampf f
Definition: Glext.h:7097
void encrypt_init()
Definition: encrypt.cpp:453
GLsizeiptr size
Definition: Glext.h:5496
void encrypt(char *text, int text_len, char *scrambled_text, int *scrambled_len, int use_8bit, bool new_encrypt)
Definition: encrypt.cpp:64
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
unsigned int uint
Definition: pstypes.h:64
int Encrypt_inited
Definition: encrypt.cpp:32
GLuint buffer
Definition: Glext.h:5492
int is_old_encrypt(char *scrambled_text)
Definition: encrypt.cpp:421
int idx
Definition: multiui.cpp:761
unsigned char ubyte
Definition: pstypes.h:62
#define NUM_LVL1_KEYS
Definition: encrypt.cpp:294
unsigned short ushort
Definition: pstypes.h:63
int is_encrypted(char *scrambled_text)
Definition: encrypt.cpp:407
GLenum GLsizei len
Definition: Glext.h:6283
ushort Lvl1_keys[NUM_LVL1_KEYS]
Definition: encrypt.cpp:295
void encrypt_new(char *text, int text_len, char *scrambled_text, int *scrambled_len)
Definition: encrypt.cpp:310
const char * encrypt_type(char *scrambled_text)
Definition: encrypt.cpp:435