Devilution
Diablo devolved - magic behind the 1996 computer game
codec.cpp
Go to the documentation of this file.
1 
6 #include "all.h"
7 
8 #include <cstddef>
9 #include <cstdint>
10 
12 
13 typedef struct CodecSignature {
14  DWORD checksum;
15  BYTE error;
17  WORD unused;
19 
20 int codec_decode(BYTE *pbSrcDst, DWORD size, char *pszPassword)
21 {
22  char buf[128];
23  char dst[SHA1HashSize];
24  int i;
25  CodecSignature *sig;
26 
27  codec_init_key(0, pszPassword);
28  if (size <= 8)
29  return 0;
30  size = size - 8;
31  if (size % 64 != 0)
32  return 0;
33  for (i = size; i != 0; pbSrcDst += 64, i -= 64) {
34  memcpy(buf, pbSrcDst, 64);
35  SHA1Result(0, dst);
36  for (int j = 0; j < 64; j++) {
37  buf[j] ^= dst[j % SHA1HashSize];
38  }
39  SHA1Calculate(0, buf, NULL);
40  memset(dst, 0, sizeof(dst));
41  memcpy(pbSrcDst, buf, 64);
42  }
43 
44  memset(buf, 0, sizeof(buf));
45  sig = (CodecSignature *)pbSrcDst;
46  if (sig->error > 0) {
47  goto error;
48  }
49 
50  SHA1Result(0, dst);
51  if (sig->checksum != *(DWORD *)dst) {
52  memset(dst, 0, sizeof(dst));
53  goto error;
54  }
55 
56  size += sig->last_chunk_size - 64;
57  SHA1Clear();
58  return size;
59 error:
60  SHA1Clear();
61  return 0;
62 }
63 
64 void codec_init_key(int unused, char *pszPassword)
65 {
66  char key[136]; // last 64 bytes are the SHA1
67  std::uint32_t rand_state = 0x7058;
68  for (std::size_t i = 0; i < sizeof(key); ++i) {
69  rand_state = rand_state * 214013 + 2531011;
70  key[i] = rand_state >> 16; // Downcasting to char keeps the 2 least-significant bytes
71  }
72 
73  char pw[64];
74  std::size_t password_i = 0;
75  for (std::size_t i = 0; i < sizeof(pw); ++i, ++password_i) {
76  if (pszPassword[password_i] == '\0')
77  password_i = 0;
78  pw[i] = pszPassword[password_i];
79  }
80 
81  char digest[SHA1HashSize];
82  SHA1Reset(0);
83  SHA1Calculate(0, pw, digest);
84  SHA1Clear();
85  for (std::size_t i = 0; i < sizeof(key); ++i)
86  key[i] ^= digest[i % SHA1HashSize];
87  memset(pw, 0, sizeof(pw));
88  memset(digest, 0, sizeof(digest));
89  for (int n = 0; n < 3; ++n) {
90  SHA1Reset(n);
91  SHA1Calculate(n, &key[72], nullptr);
92  }
93  memset(key, 0, sizeof(key));
94 }
95 
96 DWORD codec_get_encoded_len(DWORD dwSrcBytes)
97 {
98  if (dwSrcBytes % 64 != 0)
99  dwSrcBytes += 64 - (dwSrcBytes % 64);
100  return dwSrcBytes + 8;
101 }
102 
103 void codec_encode(BYTE *pbSrcDst, DWORD size, int size_64, char *pszPassword)
104 {
105  char buf[128];
106  char tmp[SHA1HashSize];
107  char dst[SHA1HashSize];
108  DWORD chunk;
109  WORD last_chunk;
110  CodecSignature *sig;
111 
112  if (size_64 != codec_get_encoded_len(size))
113  app_fatal("Invalid encode parameters");
114  codec_init_key(1, pszPassword);
115 
116  last_chunk = 0;
117  while (size != 0) {
118  chunk = size < 64 ? size : 64;
119  memcpy(buf, pbSrcDst, chunk);
120  if (chunk < 64)
121  memset(buf + chunk, 0, 64 - chunk);
122  SHA1Result(0, dst);
123  SHA1Calculate(0, buf, NULL);
124  for (int j = 0; j < 64; j++) {
125  buf[j] ^= dst[j % SHA1HashSize];
126  }
127  memset(dst, 0, sizeof(dst));
128  memcpy(pbSrcDst, buf, 64);
129  last_chunk = chunk;
130  pbSrcDst += 64;
131  size -= chunk;
132  }
133  memset(buf, 0, sizeof(buf));
134  SHA1Result(0, tmp);
135  sig = (CodecSignature *)pbSrcDst;
136  sig->error = 0;
137  sig->unused = 0;
138  sig->checksum = *(DWORD *)tmp;
139  sig->last_chunk_size = last_chunk;
140  SHA1Clear();
141 }
142 
144 
codec_init_key
void codec_init_key(int unused, char *pszPassword)
Definition: codec.cpp:64
SHA1Reset
void SHA1Reset(int n)
Definition: sha.cpp:138
all.h
app_fatal
void app_fatal(const char *pszFmt,...)
Definition: appfat.cpp:18
DEVILUTION_END_NAMESPACE
#define DEVILUTION_END_NAMESPACE
Definition: types.h:10
SHA1Calculate
void SHA1Calculate(int n, const char *data, char Message_Digest[SHA1HashSize])
Definition: sha.cpp:49
CodecSignature::unused
WORD unused
Definition: codec.cpp:17
codec_get_encoded_len
DWORD codec_get_encoded_len(DWORD dwSrcBytes)
Definition: codec.cpp:96
CodecSignature::last_chunk_size
BYTE last_chunk_size
Definition: codec.cpp:16
CodecSignature::error
BYTE error
Definition: codec.cpp:15
CodecSignature::checksum
DWORD checksum
Definition: codec.cpp:14
CodecSignature
DEVILUTION_BEGIN_NAMESPACE struct CodecSignature CodecSignature
codec_encode
void codec_encode(BYTE *pbSrcDst, DWORD size, int size_64, char *pszPassword)
Definition: codec.cpp:103
CodecSignature
Definition: codec.cpp:13
SHA1Result
void SHA1Result(int n, char Message_Digest[SHA1HashSize])
Definition: sha.cpp:35
DEVILUTION_BEGIN_NAMESPACE
Definition: sha.cpp:10
codec_decode
int codec_decode(BYTE *pbSrcDst, DWORD size, char *pszPassword)
Definition: codec.cpp:20
SHA1Clear
void SHA1Clear()
Definition: sha.cpp:30
SHA1HashSize
#define SHA1HashSize
Definition: sha.h:5