Rizin
unix-like reverse engineering framework and cli tools
privkey-find.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008 Nadia Heninger and J. Alex Halderman
2 // SPDX-FileCopyrightText: 2008 J. Alex Halderman
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 // From RSAKeyFinder 1.0 (2008-07-18)
6 // By Nadia Heninger and J. Alex Halderman
7 // Contribution to r2 by @santitox
8 // Integrated and refactored by jvoisin and spelissier
9 
10 #include <rz_search.h>
11 
12 /* The minimal length to perform a search is the sizes of
13 the sequence tag, the minimal length of the sequence,
14 the version marker and the minimal key length. */
15 #define PRIVKEY_SEARCH_MIN_LENGTH (1 + 1 + 4 + 1)
16 
17 /*Baby BER parser, just good enough for private keys.
18 
19 This is not robust to errors in the memory image, but if we added
20 some entropy testing and intelligent guessing, it could be made to be.
21 
22 Parses a single field of the key, beginning at start. Each field
23 consists of a type, a length, and a value. Puts the type of field
24 into type, the number of bytes into len, and returns a pointer to
25 the beginning of the value. */
26 static const ut8 *parse_next_field(const ut8 *start, ut32 *len) {
27  *len = 0;
28  if (!(start[1] & 0x80)) {
29  *len = (ut32)start[1];
30  return start + 2;
31  } else {
32  int i;
33  const int lensize = start[1] & 0x7f;
34  for (i = 0; i < lensize; i++) {
35  *len = (*len << 8) | start[2 + i];
36  }
37  return start + 2 + lensize;
38  }
39 }
40 
41 /* Check if `start` points to an ensemble of BER fields
42 with the format as a private key syntax. We check only the first
43 three fields of the key */
44 static int check_fields(const ut8 *start) {
45 #define KEY_MAX_LEN 26000
46  ut32 field_len = 0;
47  // Sequence field
48  const ut8 *ptr = parse_next_field(start, &field_len);
49  if (!field_len || field_len > KEY_MAX_LEN) {
50  return false;
51  }
52 
53  // Version field
54  ptr = parse_next_field(ptr, &field_len);
55  if (field_len != 1) {
56  return false;
57  }
58  ptr = ptr + field_len;
59  parse_next_field(ptr, &field_len);
60 
61  if (!field_len || field_len > KEY_MAX_LEN) {
62  return false;
63  }
64 
65  return true;
66 }
67 
68 // Finds and return index of a private key:
69 // As defined in RFC 3447 for RSA, as defined in RFC 5915 for
70 // elliptic curves and as defined in 7 of RFC 8410 for SafeCurves
72  int i, k, max, index, t;
74  RzSearchKeyword *kw;
75  const size_t old_nhits = s->nhits;
76  const ut8 rsa_versionmarker[] = { 0x02, 0x01, 0x00, 0x02 };
77  const ut8 ecc_versionmarker[] = { 0x02, 0x01, 0x01, 0x04 };
78  const ut8 safecurves_versionmarker[] = { 0x02, 0x01, 0x00, 0x30 };
79 
81  return -1;
82  }
83 
84  rz_list_foreach (s->kws, iter, kw) {
85  // Iteration until the remaining length is too small to contain a key.
86  for (i = 2; i < len - PRIVKEY_SEARCH_MIN_LENGTH; i++) {
87  if (memcmp(buf + i, rsa_versionmarker, sizeof(rsa_versionmarker)) &&
88  memcmp(buf + i, ecc_versionmarker, sizeof(ecc_versionmarker)) &&
89  memcmp(buf + i, safecurves_versionmarker, sizeof(safecurves_versionmarker))) {
90  continue;
91  }
92 
93  index = -1;
94  // Going backward maximum up to 5 characters.
95  if (i < 5) {
96  max = i;
97  } else {
98  max = 5;
99  }
100  for (k = i - 2; k >= i - max; k--) {
101  if (buf[k] == 0x30) { // The sequence identifier is 0x30
102  index = k;
103  break;
104  }
105  }
106 
107  if (index == -1) {
108  continue;
109  }
110 
111  if (check_fields(buf + index)) {
112  parse_next_field(buf + index, &kw->keyword_length);
113  t = rz_search_hit_new(s, kw, from + index);
114  if (t > 1) {
115  return s->nhits - old_nhits;
116  }
117  }
118  }
119  }
120  return -1;
121 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
#define RZ_API
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 static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
uint32_t ut32
const char * k
Definition: dsignal.c:11
int max
Definition: enough.c:225
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
#define KEY_MAX_LEN
static int check_fields(const ut8 *start)
Definition: privkey-find.c:44
RZ_API int rz_search_privkey_update(RzSearch *s, ut64 from, const ut8 *buf, int len)
Definition: privkey-find.c:71
#define PRIVKEY_SEARCH_MIN_LENGTH
Definition: privkey-find.c:15
static const ut8 * parse_next_field(const ut8 *start, ut32 *len)
Definition: privkey-find.c:26
static RzSocket * s
Definition: rtr.c:28
RZ_API int rz_search_hit_new(RzSearch *s, RzSearchKeyword *kw, ut64 addr)
Definition: search.c:107
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
ut64(WINAPI *w32_GetEnabledXStateFeatures)()