mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-27 07:00:30 +00:00
/ca update help message and add block cipher parameter
/ca initial SM4 key search implementation Add SM4 key search test Refactor cmd_search.c to have common code for key search.
This commit is contained in:
parent
ca2674228f
commit
4a01f475f3
@ -9,6 +9,7 @@ static int cmd_search(void *data, const char *input);
|
||||
#define USE_EMULATION 1
|
||||
|
||||
#define AES_SEARCH_LENGTH 40
|
||||
#define SM4_SEARCH_LENGTH 24
|
||||
#define PRIVATE_KEY_SEARCH_LENGTH 11
|
||||
|
||||
static const char *help_msg_search_wide_string[] = {
|
||||
@ -175,7 +176,7 @@ static const char *help_msg_slash_a[] = {
|
||||
|
||||
static const char *help_msg_slash_c[] = {
|
||||
"Usage: /c", "", "Search for crypto materials",
|
||||
"/ca", "", "search for AES keys expanded in memory",
|
||||
"/ca", "[?] [algo]", "search for keys expanded in memory",
|
||||
"/cc", "[algo] [digest]", "find collisions (bruteforce block length values until given checksum is found)",
|
||||
"/cd", "", "search for ASN1/DER certificates",
|
||||
"/cg", "", "search for GPG/PGP keys and signatures (Plaintext and binary form)",
|
||||
@ -243,8 +244,8 @@ struct search_parameters {
|
||||
PJ *pj;
|
||||
int outmode; // 0 or R_MODE_RADARE or R_MODE_JSON
|
||||
bool inverse;
|
||||
bool aes_search;
|
||||
bool privkey_search;
|
||||
bool key_search;
|
||||
int key_search_len;
|
||||
int c; // used for progress
|
||||
};
|
||||
|
||||
@ -2618,8 +2619,8 @@ static void do_string_search(RCore *core, RInterval search_itv, struct search_pa
|
||||
if (r_cons_is_breaked ()) {
|
||||
break;
|
||||
}
|
||||
RSearchKeyword *kw = r_list_first (core->search->kws);
|
||||
if (param->outmode != R_MODE_JSON) {
|
||||
RSearchKeyword *kw = r_list_first (core->search->kws);
|
||||
int lenstr = kw? kw->keyword_length: 0;
|
||||
const char *bytestr = lenstr > 1? "bytes": "byte";
|
||||
eprintf ("Searching %d %s in [0x%"PFMT64x "-0x%"PFMT64x "]\n",
|
||||
@ -2662,15 +2663,10 @@ static void do_string_search(RCore *core, RInterval search_itv, struct search_pa
|
||||
(void)r_io_read_at (core->io, at, buf, len);
|
||||
}
|
||||
r_search_update (core->search, at, buf, len);
|
||||
if (param->aes_search) {
|
||||
if (param->key_search) {
|
||||
// Adjust length to search between blocks.
|
||||
if (len == core->blocksize) {
|
||||
len -= AES_SEARCH_LENGTH - 1;
|
||||
}
|
||||
} else if (param->privkey_search) {
|
||||
// Adjust length to search between blocks.
|
||||
if (len == core->blocksize) {
|
||||
len -= PRIVATE_KEY_SEARCH_LENGTH - 1;
|
||||
len -= param->key_search_len - 1;
|
||||
}
|
||||
}
|
||||
if (core->search->maxhits > 0 && core->search->nhits >= core->search->maxhits) {
|
||||
@ -3298,8 +3294,8 @@ static int cmd_search(void *data, const char *input) {
|
||||
.cmd_hit = r_config_get (core->config, "cmd.hit"),
|
||||
.outmode = 0,
|
||||
.inverse = false,
|
||||
.aes_search = false,
|
||||
.privkey_search = false,
|
||||
.key_search = false,
|
||||
.key_search_len = 0,
|
||||
.c = 0,
|
||||
};
|
||||
if (!param.cmd_hit) {
|
||||
@ -3836,16 +3832,39 @@ reread:
|
||||
case 'a': // "/ca"
|
||||
{
|
||||
RSearchKeyword *kw;
|
||||
if (input[2] == 'j') {
|
||||
param.outmode = R_MODE_JSON;
|
||||
|
||||
char *space = strchr (input, ' ');
|
||||
const char *arg = space? r_str_trim_head_ro (space + 1): NULL;
|
||||
if (!arg || *(space - 1) == '?') {
|
||||
eprintf ("Usage: /ca [algo]\n");
|
||||
eprintf ("Currently supported block ciphers:\n");
|
||||
eprintf (" aes\n");
|
||||
eprintf (" sm4\n");
|
||||
goto beach;
|
||||
} else {
|
||||
kw = r_search_keyword_new_hexmask ("00", NULL);
|
||||
if (input[2] == 'j') {
|
||||
param.outmode = R_MODE_JSON;
|
||||
}
|
||||
if (!strcmp (arg, "aes")) {
|
||||
// AES search is done over 40 bytes
|
||||
param.key_search_len = AES_SEARCH_LENGTH;
|
||||
r_search_reset (core->search, R_SEARCH_AES);
|
||||
} else if (!strcmp (arg, "sm4")) {
|
||||
param.key_search_len = SM4_SEARCH_LENGTH;
|
||||
r_search_reset (core->search, R_SEARCH_SM4);
|
||||
} else {
|
||||
eprintf ("Unsupported block ciphers: %s\n", arg);
|
||||
goto beach;
|
||||
}
|
||||
if (core->blocksize < param.key_search_len) {
|
||||
eprintf ("Block size must be bigger than %d bytes for the search\n", param.key_search_len);
|
||||
goto beach;
|
||||
}
|
||||
r_search_kw_add (search, kw);
|
||||
r_search_begin (core->search);
|
||||
param.key_search = true;
|
||||
}
|
||||
kw = r_search_keyword_new_hexmask ("00", NULL);
|
||||
// AES search is done over 40 bytes
|
||||
kw->keyword_length = AES_SEARCH_LENGTH;
|
||||
r_search_reset (core->search, R_SEARCH_AES);
|
||||
r_search_kw_add (search, kw);
|
||||
r_search_begin (core->search);
|
||||
param.aes_search = true;
|
||||
break;
|
||||
}
|
||||
case 'r': // "/cr"
|
||||
@ -3860,7 +3879,7 @@ reread:
|
||||
r_search_reset (core->search, R_SEARCH_PRIV_KEY);
|
||||
r_search_kw_add (search, kw);
|
||||
r_search_begin (core->search);
|
||||
param.privkey_search = true;
|
||||
param.key_search = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -5,6 +5,7 @@
|
||||
* */
|
||||
|
||||
#include <r_crypto.h>
|
||||
#include <r_crypto/r_sm4.h>
|
||||
#include <r_util.h>
|
||||
#include <memory.h>
|
||||
|
||||
@ -17,14 +18,6 @@
|
||||
/* Family Key FK */
|
||||
static const ut32 FK[4] = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
|
||||
|
||||
/* Constant Key CK */
|
||||
static const ut32 CK[32] = {
|
||||
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
|
||||
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
|
||||
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
|
||||
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
|
||||
};
|
||||
|
||||
/* SM4 S-boxes */
|
||||
static const ut8 Sbox[256] = {
|
||||
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
|
||||
@ -46,7 +39,7 @@ static const ut8 Sbox[256] = {
|
||||
};
|
||||
|
||||
/* Calculating next round keys */
|
||||
static ut32 sm4_RK(ut32 rk) {
|
||||
R_API ut32 sm4_RK(ut32 rk) {
|
||||
ut8 a[4];
|
||||
ut8 b[4];
|
||||
ut32 lb = 0;
|
||||
@ -125,7 +118,7 @@ static bool sm4_init(RCryptoJob *cj, ut32 *sk, const ut8 *key, int keylen, int d
|
||||
k[2] = MK[2] ^ FK[2];
|
||||
k[3] = MK[3] ^ FK[3];
|
||||
for (i = 0; i < 32; i++) {
|
||||
k[i + 4] = k[i] ^ (sm4_RK (k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]));
|
||||
k[i + 4] = k[i] ^ (sm4_RK (k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ sm4_CK[i]));
|
||||
|
||||
if (dir == 0) {
|
||||
cj->sm4_sk[i] = k[i + 4];
|
||||
|
24
libr/include/r_crypto/r_sm4.h
Normal file
24
libr/include/r_crypto/r_sm4.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef R_SM4_H
|
||||
#define R_SM4_H
|
||||
|
||||
#include <r_util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Constant Key CK */
|
||||
static const ut32 sm4_CK[32] = {
|
||||
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
|
||||
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
|
||||
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
|
||||
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
|
||||
};
|
||||
|
||||
R_API ut32 sm4_RK(ut32 rk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // R_SM4_H
|
@ -21,6 +21,7 @@ enum {
|
||||
R_SEARCH_STRING,
|
||||
R_SEARCH_XREFS,
|
||||
R_SEARCH_AES,
|
||||
R_SEARCH_SM4,
|
||||
R_SEARCH_PRIV_KEY,
|
||||
R_SEARCH_DELTAKEY,
|
||||
R_SEARCH_MAGIC,
|
||||
|
@ -1,7 +1,7 @@
|
||||
include ../config.mk
|
||||
|
||||
NAME=r_search
|
||||
OBJS=search.o bytepat.o strings.o aes_find.o privkey_find.o
|
||||
OBJS=search.o bytepat.o strings.o aes_find.o privkey_find.o sm4_find.o
|
||||
OBJS+=regexp.o keyword.o uds.o rabin_karp.o
|
||||
# OBJ+=rsakey.o
|
||||
R2DEPS=r_util
|
||||
|
@ -7,6 +7,7 @@ r_search_sources = [
|
||||
'privkey_find.c',
|
||||
'rabin_karp.c',
|
||||
'search.c',
|
||||
'sm4_find.c',
|
||||
'strings.c'
|
||||
]
|
||||
|
||||
|
@ -85,6 +85,7 @@ R_API int r_search_set_mode(RSearch *s, int mode) {
|
||||
case R_SEARCH_KEYWORD: s->update = search_kw_update; break;
|
||||
case R_SEARCH_REGEXP: s->update = search_regexp_update; break;
|
||||
case R_SEARCH_AES: s->update = search_aes_update; break;
|
||||
case R_SEARCH_SM4: s->update = search_sm4_update; break;
|
||||
case R_SEARCH_PRIV_KEY: s->update = search_privkey_update; break;
|
||||
case R_SEARCH_STRING: s->update = search_strings_update; break;
|
||||
case R_SEARCH_DELTAKEY: s->update = search_deltakey_update; break;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// To keep update function out of public r_search API
|
||||
R_IPI int search_kw_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_aes_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_sm4_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_privkey_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_deltakey_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
R_IPI int search_strings_update(RSearch *s, ut64 from, const ut8 *buf, int len);
|
||||
|
36
libr/search/sm4_find.c
Normal file
36
libr/search/sm4_find.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* radare2 - LGPL - Copyright 2022 - Sylvain Pelissier */
|
||||
#include <r_crypto/r_sm4.h>
|
||||
#include <r_search.h>
|
||||
#include <r_util.h>
|
||||
|
||||
#define SM4_SEARCH_LENGTH 24
|
||||
#define SM4_KEY_LENGTH 16
|
||||
|
||||
static bool sm4_key_test(const unsigned char *buf) {
|
||||
ut32 *ptr = (ut32 *)buf;
|
||||
return (ptr[4] == (ptr[0] ^ (sm4_RK (ptr[1] ^ ptr[2] ^ ptr[3] ^ sm4_CK[4])))) && (ptr[5] == (ptr[1] ^ (sm4_RK (ptr[2] ^ ptr[3] ^ ptr[4] ^ sm4_CK[5]))));
|
||||
}
|
||||
|
||||
R_IPI int search_sm4_update(RSearch *s, ut64 from, const ut8 *buf, int len) {
|
||||
int i, t, last = len - SM4_SEARCH_LENGTH;
|
||||
RListIter *iter;
|
||||
RSearchKeyword *kw;
|
||||
const int old_nhits = s->nhits;
|
||||
|
||||
r_list_foreach (s->kws, iter, kw) {
|
||||
for (i = 0; i < last + 1; i++) {
|
||||
if (sm4_key_test (buf + i)) {
|
||||
kw->keyword_length = SM4_KEY_LENGTH;
|
||||
t = r_search_hit_new (s, kw, from + i);
|
||||
if (!t) {
|
||||
return -1;
|
||||
}
|
||||
if (t > 1) {
|
||||
return s->nhits - old_nhits;
|
||||
}
|
||||
i += SM4_SEARCH_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
NAME=cmd.hit for /ca
|
||||
FILE=bins/other/aes.dump
|
||||
CMDS=/ca
|
||||
CMDS=/ca aes
|
||||
EXPECT=<<EOF
|
||||
0x0000001e hit0_0 0000000000000000000000000000000000000000000000000000000000000000
|
||||
EOF
|
||||
@ -8,15 +8,23 @@ RUN
|
||||
|
||||
NAME=cmd.hit for /ca
|
||||
FILE=bins/other/aes_192.dump
|
||||
CMDS=/ca
|
||||
CMDS=/ca aes
|
||||
EXPECT=<<EOF
|
||||
0x000000fa hit0_0 000102030405060708090a0b0c0d0e0f1011121314151617
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=cmd.hit for /ca sm4
|
||||
FILE=bins/other/sm4_key_schedule.bin
|
||||
CMDS=/ca sm4
|
||||
EXPECT=<<EOF
|
||||
0x000000ff hit0_0 f98621f1612b6641db28e44757dbe32c
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=cmd.hit for /caj
|
||||
FILE=bins/other/aes_192.dump
|
||||
CMDS=/caj
|
||||
CMDS=/caj aes
|
||||
EXPECT=<<EOF
|
||||
[{"offset":250,"type":"hexpair","data":"000102030405060708090a0b0c0d0e0f1011121314151617"}]
|
||||
EOF
|
||||
|
Loading…
Reference in New Issue
Block a user