Rizin
unix-like reverse engineering framework and cli tools
crypto_aes_cbc.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016-2017 rakholiyajenish.07 <rakholiyajenish.07@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 #include <aes.h>
8 
9 typedef struct aes_cbc_context_t {
10  struct aes_ctx st;
11  bool iv_set;
12  ut8 iv[32];
14 
15 static void encryptaes(struct aes_ctx *ctx, ut8 *in, ut8 *out) {
16  switch (ctx->key_size) {
17  case AES128_KEY_SIZE:
18  aes128_encrypt(&ctx->u.ctx128, AES_BLOCK_SIZE, out, in);
19  break;
20  case AES192_KEY_SIZE:
21  aes192_encrypt(&ctx->u.ctx192, AES_BLOCK_SIZE, out, in);
22  break;
23  case AES256_KEY_SIZE:
24  aes256_encrypt(&ctx->u.ctx256, AES_BLOCK_SIZE, out, in);
25  break;
26  default:
28  break;
29  }
30 }
31 
32 static void decryptaes(struct aes_ctx *ctx, ut8 *in, ut8 *out) {
33  switch (ctx->key_size) {
34  case AES128_KEY_SIZE:
35  aes128_decrypt(&ctx->u.ctx128, AES_BLOCK_SIZE, out, in);
36  break;
37  case AES192_KEY_SIZE:
38  aes192_decrypt(&ctx->u.ctx192, AES_BLOCK_SIZE, out, in);
39  break;
40  case AES256_KEY_SIZE:
41  aes256_decrypt(&ctx->u.ctx256, AES_BLOCK_SIZE, out, in);
42  break;
43  default:
45  break;
46  }
47 }
48 
49 static bool aes_cbc_set_key(RzCrypto *cry, const ut8 *key, int keylen, int mode, int direction) {
50  rz_return_val_if_fail(cry->user && key, false);
51 
52  if (!(keylen == AES128_KEY_SIZE || keylen == AES192_KEY_SIZE || keylen == AES256_KEY_SIZE)) {
53  return false;
54  }
55  AesCbcCtx *ctx = (AesCbcCtx *)cry->user;
56 
57  ctx->st.key_size = keylen;
58  switch (keylen) {
59  case AES128_KEY_SIZE:
60  if (direction == RZ_CRYPTO_DIR_ENCRYPT) {
61  aes128_set_encrypt_key(&ctx->st.u.ctx128, key);
62  } else {
63  aes128_set_decrypt_key(&ctx->st.u.ctx128, key);
64  }
65  break;
66  case AES192_KEY_SIZE:
67  if (direction == RZ_CRYPTO_DIR_ENCRYPT) {
68  aes192_set_encrypt_key(&ctx->st.u.ctx192, key);
69  } else {
70  aes192_set_decrypt_key(&ctx->st.u.ctx192, key);
71  }
72  break;
73  case AES256_KEY_SIZE:
74  if (direction == RZ_CRYPTO_DIR_ENCRYPT) {
75  aes256_set_encrypt_key(&ctx->st.u.ctx256, key);
76  } else {
77  aes256_set_decrypt_key(&ctx->st.u.ctx256, key);
78  }
79  break;
80  default:
82  break;
83  }
84  cry->dir = direction;
85  return true;
86 }
87 
88 static int aes_cbc_get_key_size(RzCrypto *cry) {
89  rz_return_val_if_fail(cry->user, 0);
90  AesCbcCtx *ctx = (AesCbcCtx *)cry->user;
91 
92  return ctx->st.key_size;
93 }
94 
95 static bool aes_cbc_set_iv(RzCrypto *cry, const ut8 *iv_src, int ivlen) {
96  rz_return_val_if_fail(cry->user && iv_src, false);
97  AesCbcCtx *ctx = (AesCbcCtx *)cry->user;
98 
99  if (ivlen != AES_BLOCK_SIZE) {
100  return false;
101  }
102  memcpy(ctx->iv, iv_src, AES_BLOCK_SIZE);
103  ctx->iv_set = true;
104  return true;
105 }
106 
107 static bool aes_cbc_use(const char *algo) {
108  return algo && !strcmp(algo, "aes-cbc");
109 }
110 
111 static bool update(RzCrypto *cry, const ut8 *buf, int len) {
112  rz_return_val_if_fail(cry->user, false);
113  AesCbcCtx *ctx = (AesCbcCtx *)cry->user;
114 
115  if (len < 1) {
116  return false;
117  }
118 
119  if (!ctx->iv_set) {
120  eprintf("IV not set. Use -I [iv]\n");
121  return false;
122  }
123  const int diff = (AES_BLOCK_SIZE - (len % AES_BLOCK_SIZE)) % AES_BLOCK_SIZE;
124  const int size = len + diff;
125  const int blocks = size / AES_BLOCK_SIZE;
126 
127  ut8 *const obuf = calloc(1, size);
128  if (!obuf) {
129  return false;
130  }
131 
132  ut8 *const ibuf = calloc(1, size);
133  if (!ibuf) {
134  free(obuf);
135  return false;
136  }
137 
138  memset(ibuf, 0, size);
139  memcpy(ibuf, buf, len);
140 
141  if (diff) {
142  ibuf[len] = 8; // 0b1000;
143  }
144 
145  int i, j;
146  if (cry->dir == RZ_CRYPTO_DIR_ENCRYPT) {
147  for (i = 0; i < blocks; i++) {
148  for (j = 0; j < AES_BLOCK_SIZE; j++) {
149  ibuf[i * AES_BLOCK_SIZE + j] ^= ctx->iv[j];
150  }
151  encryptaes(&ctx->st, ibuf + AES_BLOCK_SIZE * i, obuf + AES_BLOCK_SIZE * i);
153  }
154  } else {
155  for (i = 0; i < blocks; i++) {
156  decryptaes(&ctx->st, ibuf + AES_BLOCK_SIZE * i, obuf + AES_BLOCK_SIZE * i);
157  for (j = 0; j < AES_BLOCK_SIZE; j++) {
158  obuf[i * AES_BLOCK_SIZE + j] ^= ctx->iv[j];
159  }
161  }
162  }
163 
164  rz_crypto_append(cry, obuf, size);
165  free(obuf);
166  free(ibuf);
167  return true;
168 }
169 
170 static bool final(RzCrypto *cry, const ut8 *buf, int len) {
171  return update(cry, buf, len);
172 }
173 
174 static bool aes_cbc_init(RzCrypto *cry) {
175  rz_return_val_if_fail(cry, false);
176 
177  cry->user = RZ_NEW0(AesCbcCtx);
178  return cry->user != NULL;
179 }
180 
181 static bool aes_cbc_fini(RzCrypto *cry) {
182  rz_return_val_if_fail(cry, false);
183 
184  free(cry->user);
185  return true;
186 }
187 
189  .name = "aes-cbc",
190  .author = "rakholiyajenish.07",
191  .license = "LGPL-3",
192  .set_key = aes_cbc_set_key,
193  .get_key_size = aes_cbc_get_key_size,
194  .set_iv = aes_cbc_set_iv,
195  .use = aes_cbc_use,
196  .update = update,
197  .final = final,
198  .init = aes_cbc_init,
199  .fini = aes_cbc_fini,
200 };
201 
202 #ifndef RZ_PLUGIN_INCORE
205  .data = &rz_crypto_plugin_aes_cbc,
206  .version = RZ_VERSION
207 };
208 #endif
size_t len
Definition: 6502dis.c:15
void aes128_encrypt(const struct aes128_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src)
void aes128_decrypt(const struct aes128_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src)
void aes128_set_encrypt_key(struct aes128_ctx *ctx, const uint8_t *key)
#define AES192_KEY_SIZE
Definition: aes.h:71
void aes128_set_decrypt_key(struct aes128_ctx *ctx, const uint8_t *key)
void aes192_encrypt(const struct aes192_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src)
void aes256_encrypt(const struct aes256_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src)
#define AES256_KEY_SIZE
Definition: aes.h:72
void aes256_set_decrypt_key(struct aes256_ctx *ctx, const uint8_t *key)
void aes256_set_encrypt_key(struct aes256_ctx *ctx, const uint8_t *key)
void aes192_set_decrypt_key(struct aes192_ctx *ctx, const uint8_t *key)
void aes256_decrypt(const struct aes256_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src)
#define AES128_KEY_SIZE
Definition: aes.h:70
void aes192_decrypt(const struct aes192_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src)
void aes192_set_encrypt_key(struct aes192_ctx *ctx, const uint8_t *key)
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#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 aes_cbc_set_iv(RzCrypto *cry, const ut8 *iv_src, int ivlen)
struct aes_cbc_context_t AesCbcCtx
static bool update(RzCrypto *cry, const ut8 *buf, int len)
RZ_API RzLibStruct rizin_plugin
static int aes_cbc_get_key_size(RzCrypto *cry)
static void encryptaes(struct aes_ctx *ctx, ut8 *in, ut8 *out)
static bool aes_cbc_fini(RzCrypto *cry)
static void decryptaes(struct aes_ctx *ctx, ut8 *in, ut8 *out)
static bool aes_cbc_use(const char *algo)
RzCryptoPlugin rz_crypto_plugin_aes_cbc
static bool aes_cbc_set_key(RzCrypto *cry, const ut8 *key, int keylen, int mode, int direction)
static bool aes_cbc_init(RzCrypto *cry)
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
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
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
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#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
struct aes_ctx st
Definition: aes.h:151
const char * name
Definition: rz_crypto.h:41
void * user
Definition: rz_crypto.h:36
uint64_t blocks
Definition: list.c:104
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
static unsigned char * obuf
Definition: z80asm.c:36
#define AES_BLOCK_SIZE
Definition: zipint.h:77