Rizin
unix-like reverse engineering framework and cli tools
crypto_rc2.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016 Aneesh Dogra <lionaneesh@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_lib.h>
5 #include <rz_crypto.h>
6 #include <rz_util.h>
7 
8 #define BITS 1024
9 #define RC2_KEY_SIZE 64 // bytes
10 #define BLOCK_SIZE 8 // bytes
11 
12 static const ut8 PITABLE[256] = {
13  0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED, 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
14  0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E, 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
15  0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13, 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
16  0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B, 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
17  0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C, 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
18  0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1, 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
19  0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57, 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
20  0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7, 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
21  0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7, 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
22  0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74, 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
23  0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC, 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
24  0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A, 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
25  0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE, 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
26  0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C, 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
27  0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0, 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
28  0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77, 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
29 };
30 
31 struct rc2_state {
33  int key_size;
34 };
35 
36 // takes a 8-128 len ut8 key
37 // expands it to a 64 len ut16 key
38 static bool rc2_expandKey(struct rc2_state *state, const ut8 *key, int key_len) {
39  int i;
40 
41  if (key_len < 1 || key_len > 128) {
42  return false;
43  }
44  memcpy(state->ekey, key, key_len);
45 
46  // first loop
47  for (i = key_len; i < 128; i++) {
48  ((ut8 *)state->ekey)[i] = PITABLE[(((ut8 *)state->ekey)[i - key_len] + ((ut8 *)state->ekey)[i - 1]) & 255];
49  }
50 
51  int ekey_len = (BITS + 7) >> 3;
52  i = 128 - ekey_len;
53  ((ut8 *)state->ekey)[i] = PITABLE[((ut8 *)state->ekey)[i] & (255 >> (7 & -BITS))];
54 
55  // second loop
56  while (i--) {
57  ((ut8 *)state->ekey)[i] = PITABLE[((ut8 *)state->ekey)[i + 1] ^ ((ut8 *)state->ekey)[i + ekey_len]];
58  }
59 
60  // generate the ut16 key
61  for (i = RC2_KEY_SIZE - 1; i >= 0; i--) {
62  state->ekey[i] = ((ut8 *)state->ekey)[i * 2] + (((ut8 *)state->ekey)[i * 2 + 1] << 8);
63  }
64 
65  return true;
66 }
67 
68 static void rc2_crypt8(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf) {
69  int i;
70  ut16 x76, x54, x32, x10;
71 
72  x76 = (inbuf[7] << 8) | inbuf[6];
73  x54 = (inbuf[5] << 8) | inbuf[4];
74  x32 = (inbuf[3] << 8) | inbuf[2];
75  x10 = (inbuf[1] << 8) | inbuf[0];
76 
77  for (i = 0; i < 16; i++) {
78  x10 += ((x32 & ~x76) + (x54 & x76)) + state->ekey[4 * i + 0];
79  x10 = (x10 << 1) + (x10 >> 15 & 1);
80 
81  x32 += ((x54 & ~x10) + (x76 & x10)) + state->ekey[4 * i + 1];
82  x32 = (x32 << 2) + (x32 >> 14 & 3);
83 
84  x54 += ((x76 & ~x32) + (x10 & x32)) + state->ekey[4 * i + 2];
85  x54 = (x54 << 3) + (x54 >> 13 & 7);
86 
87  x76 += ((x10 & ~x54) + (x32 & x54)) + state->ekey[4 * i + 3];
88  x76 = (x76 << 5) + (x76 >> 11 & 31);
89 
90  if (i == 4 || i == 10) {
91  x10 += state->ekey[x76 & 63];
92  x32 += state->ekey[x10 & 63];
93  x54 += state->ekey[x32 & 63];
94  x76 += state->ekey[x54 & 63];
95  }
96  }
97 
98  outbuf[0] = (ut8)x10;
99  outbuf[1] = (ut8)(x10 >> 8);
100  outbuf[2] = (ut8)x32;
101  outbuf[3] = (ut8)(x32 >> 8);
102  outbuf[4] = (ut8)x54;
103  outbuf[5] = (ut8)(x54 >> 8);
104  outbuf[6] = (ut8)x76;
105  outbuf[7] = (ut8)(x76 >> 8);
106 }
107 
108 static void rc2_dcrypt8(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf) {
109  int i;
110  ut16 x76, x54, x32, x10;
111 
112  x76 = (inbuf[7] << 8) | inbuf[6];
113  x54 = (inbuf[5] << 8) | inbuf[4];
114  x32 = (inbuf[3] << 8) | inbuf[2];
115  x10 = (inbuf[1] << 8) | inbuf[0];
116 
117  for (i = 15; i >= 0; i--) {
118  x76 &= 65535;
119  x76 = (x76 << 11) | (x76 >> 5);
120  x76 -= ((x10 & ~x54) | (x32 & x54)) + state->ekey[4 * i + 3];
121 
122  x76 &= 65535;
123  x54 = (x54 << 13) | (x54 >> 3);
124  x54 -= ((x76 & ~x32) | (x10 & x32)) + state->ekey[4 * i + 2];
125 
126  x32 &= 65535;
127  x32 = (x32 << 14) | (x32 >> 2);
128  x32 -= ((x54 & ~x10) | (x76 & x10)) + state->ekey[4 * i + 1];
129 
130  x10 &= 65535;
131  x10 = (x10 << 15) | (x10 >> 1);
132  x10 -= ((x32 & ~x76) | (x54 & x76)) + state->ekey[4 * i + 0];
133 
134  if (i == 5 || i == 11) {
135  x76 -= state->ekey[x54 & 63];
136  x54 -= state->ekey[x32 & 63];
137  x32 -= state->ekey[x10 & 63];
138  x10 -= state->ekey[x76 & 63];
139  }
140  }
141 
142  outbuf[0] = (ut8)x10;
143  outbuf[1] = (ut8)(x10 >> 8);
144  outbuf[2] = (ut8)x32;
145  outbuf[3] = (ut8)(x32 >> 8);
146  outbuf[4] = (ut8)x54;
147  outbuf[5] = (ut8)(x54 >> 8);
148  outbuf[6] = (ut8)x76;
149  outbuf[7] = (ut8)(x76 >> 8);
150 }
151 
152 static void rc2_dcrypt(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf, int buflen) {
153  int i;
154  char data_block[BLOCK_SIZE + 1] = { 0 };
155  int idx = 0;
156  char dcrypted_block[BLOCK_SIZE + 1] = { 0 };
157  char *ptr = (char *)outbuf;
158 
159  for (i = 0; i < buflen; i++) {
160  data_block[idx] = inbuf[i];
161  idx += 1;
162  if (idx % BLOCK_SIZE == 0) {
163  rc2_dcrypt8(state, (const ut8 *)data_block, (ut8 *)dcrypted_block);
164  memcpy(ptr, dcrypted_block, BLOCK_SIZE);
165  ptr += BLOCK_SIZE;
166  idx = 0;
167  }
168  }
169 }
170 
171 static void rc2_crypt(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf, int buflen) {
172  int i;
173  char data_block[BLOCK_SIZE] = { 0 };
174  int idx = 0;
175 
176  char crypted_block[BLOCK_SIZE] = { 0 };
177  char *ptr = (char *)outbuf;
178 
179  // divide it into blocks of BLOCK_SIZE
180  for (i = 0; i < buflen; i++) {
181  data_block[idx] = inbuf[i];
182  idx += 1;
183  if (idx % BLOCK_SIZE == 0) {
184  rc2_crypt8(state, (const ut8 *)data_block, (ut8 *)crypted_block);
185  strncpy(ptr, crypted_block, BLOCK_SIZE);
186  ptr += BLOCK_SIZE;
187  idx = 0;
188  }
189  }
190 
191  if (idx % 8 && idx < BLOCK_SIZE) {
192  while (idx % 8 && idx < BLOCK_SIZE) {
193  data_block[idx++] = 0;
194  }
195  rc2_crypt8(state, (const ut8 *)data_block, (ut8 *)crypted_block);
196  strncpy(ptr, crypted_block, 8);
197  }
198 }
199 
201 
202 static bool rc2_set_key(RzCrypto *cry, const ut8 *key, int keylen, int mode, int direction) {
203  rz_return_val_if_fail(cry->user && key, false);
204  struct rc2_state *state = (struct rc2_state *)cry->user;
205 
206  cry->dir = direction;
207  state->key_size = 1024;
208  return rc2_expandKey(state, key, keylen);
209 }
210 
211 static int rc2_get_key_size(RzCrypto *cry) {
212  rz_return_val_if_fail(cry->user, 0);
213  struct rc2_state *state = (struct rc2_state *)cry->user;
214  return state->key_size;
215 }
216 
217 static bool rc2_use(const char *algo) {
218  return !strcmp(algo, "rc2");
219 }
220 
221 static bool update(RzCrypto *cry, const ut8 *buf, int len) {
222  rz_return_val_if_fail(cry->user, false);
223  struct rc2_state *state = (struct rc2_state *)cry->user;
224 
225  ut8 *obuf = calloc(1, len);
226  if (!obuf) {
227  return false;
228  }
229  if (cry->dir == RZ_CRYPTO_DIR_ENCRYPT) {
230  rc2_crypt(state, buf, obuf, len);
231  } else {
233  }
234  rz_crypto_append(cry, obuf, len);
235  free(obuf);
236  return true;
237 }
238 
239 static bool final(RzCrypto *cry, const ut8 *buf, int len) {
240  return update(cry, buf, len);
241 }
242 
243 static bool rc2_init(RzCrypto *cry) {
244  rz_return_val_if_fail(cry, false);
245 
246  cry->user = RZ_NEW0(struct rc2_state);
247  return cry->user != NULL;
248 }
249 
250 static bool rc2_fini(RzCrypto *cry) {
251  rz_return_val_if_fail(cry, false);
252 
253  free(cry->user);
254  return true;
255 }
256 
258  .name = "rc2",
259  .author = "lionaneesh",
260  .license = "LGPL-3",
261  .set_key = rc2_set_key,
262  .get_key_size = rc2_get_key_size,
263  .use = rc2_use,
264  .update = update,
265  .final = final,
266  .init = rc2_init,
267  .fini = rc2_fini,
268 };
269 
270 #ifndef RZ_PLUGIN_INCORE
273  .data = &rz_crypto_plugin_rc2,
274  .version = RZ_VERSION
275 };
276 #endif
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RZ_API int rz_crypto_append(RzCrypto *cry, const ut8 *buf, int len)
Definition: crypto.c:175
static bool rc2_init(RzCrypto *cry)
Definition: crypto_rc2.c:243
static bool rc2_expandKey(struct rc2_state *state, const ut8 *key, int key_len)
Definition: crypto_rc2.c:38
static const ut8 PITABLE[256]
Definition: crypto_rc2.c:12
static void rc2_crypt(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf, int buflen)
Definition: crypto_rc2.c:171
static bool update(RzCrypto *cry, const ut8 *buf, int len)
Definition: crypto_rc2.c:221
static void rc2_crypt8(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf)
Definition: crypto_rc2.c:68
RZ_API RzLibStruct rizin_plugin
Definition: crypto_rc2.c:271
static void rc2_dcrypt8(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf)
Definition: crypto_rc2.c:108
#define BITS
Definition: crypto_rc2.c:8
static void rc2_dcrypt(struct rc2_state *state, const ut8 *inbuf, ut8 *outbuf, int buflen)
Definition: crypto_rc2.c:152
static int rc2_get_key_size(RzCrypto *cry)
Definition: crypto_rc2.c:211
static bool rc2_fini(RzCrypto *cry)
Definition: crypto_rc2.c:250
#define BLOCK_SIZE
Definition: crypto_rc2.c:10
#define RC2_KEY_SIZE
Definition: crypto_rc2.c:9
RzCryptoPlugin rz_crypto_plugin_rc2
Definition: crypto_rc2.c:257
static bool rc2_use(const char *algo)
Definition: crypto_rc2.c:217
static bool rc2_set_key(RzCrypto *cry, const ut8 *key, int keylen, int mode, int direction)
Definition: crypto_rc2.c:202
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
#define ut8
Definition: dcpu16.h:8
uint16_t ut16
unsigned char outbuf[SIZE]
Definition: gun.c:162
unsigned char inbuf[SIZE]
Definition: gun.c:161
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
int idx
Definition: setup.py:197
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_CRYPTO_DIR_ENCRYPT
Definition: rz_crypto.h:23
@ RZ_LIB_TYPE_CRYPTO
Definition: rz_lib.h:81
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_VERSION
Definition: rz_version.h:8
int key_size
Definition: crypto_rc2.c:33
ut16 ekey[RC2_KEY_SIZE]
Definition: crypto_rc2.c:32
const char * name
Definition: rz_crypto.h:41
void * user
Definition: rz_crypto.h:36
Definition: dis.h:43
ut64 buflen
Definition: core.c:76
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
static unsigned char * obuf
Definition: z80asm.c:36