diff options
Diffstat (limited to 'utils/imxtools/misc.c')
-rw-r--r-- | utils/imxtools/misc.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/utils/imxtools/misc.c b/utils/imxtools/misc.c new file mode 100644 index 0000000000..8d7cea89d7 --- /dev/null +++ b/utils/imxtools/misc.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include <stdlib.h> | ||
22 | #include <stdio.h> | ||
23 | #include <time.h> | ||
24 | #include <ctype.h> | ||
25 | #include "misc.h" | ||
26 | |||
27 | bool g_debug = false; | ||
28 | |||
29 | /** | ||
30 | * Misc | ||
31 | */ | ||
32 | |||
33 | void *memdup(void *p, size_t len) | ||
34 | { | ||
35 | void *cpy = xmalloc(len); | ||
36 | memcpy(cpy, p, len); | ||
37 | return cpy; | ||
38 | } | ||
39 | |||
40 | void generate_random_data(void *buf, size_t sz) | ||
41 | { | ||
42 | FILE *rand_fd = fopen("/dev/urandom", "rb"); | ||
43 | if(rand_fd == NULL) | ||
44 | bugp("failed to open /dev/urandom"); | ||
45 | if(fread(buf, 1, sz, rand_fd) != sz) | ||
46 | bugp("failed to read /dev/urandom"); | ||
47 | fclose(rand_fd); | ||
48 | } | ||
49 | |||
50 | void *xmalloc(size_t s) | ||
51 | { | ||
52 | void * r = malloc(s); | ||
53 | if(!r) bugp("malloc"); | ||
54 | return r; | ||
55 | } | ||
56 | |||
57 | int convxdigit(char digit, byte *val) | ||
58 | { | ||
59 | if(digit >= '0' && digit <= '9') | ||
60 | { | ||
61 | *val = digit - '0'; | ||
62 | return 0; | ||
63 | } | ||
64 | else if(digit >= 'A' && digit <= 'F') | ||
65 | { | ||
66 | *val = digit - 'A' + 10; | ||
67 | return 0; | ||
68 | } | ||
69 | else if(digit >= 'a' && digit <= 'f') | ||
70 | { | ||
71 | *val = digit - 'a' + 10; | ||
72 | return 0; | ||
73 | } | ||
74 | else | ||
75 | return 1; | ||
76 | } | ||
77 | |||
78 | /* helper function to augment an array, free old array */ | ||
79 | void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt) | ||
80 | { | ||
81 | void *p = xmalloc(elem_sz * (cnt + aug_cnt)); | ||
82 | memcpy(p, arr, elem_sz * cnt); | ||
83 | memcpy(p + elem_sz * cnt, aug, elem_sz * aug_cnt); | ||
84 | free(arr); | ||
85 | return p; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Key file parsing | ||
90 | */ | ||
91 | int g_nr_keys; | ||
92 | key_array_t g_key_array; | ||
93 | |||
94 | bool parse_key(char **pstr, struct crypto_key_t *key) | ||
95 | { | ||
96 | char *str = *pstr; | ||
97 | /* ignore spaces */ | ||
98 | while(isspace(*str)) | ||
99 | str++; | ||
100 | /* CRYPTO_KEY: 32 hex characters | ||
101 | * CRYPTO_USBOTP: usbotp(vid:pid) where vid and pid are hex numbers */ | ||
102 | if(isxdigit(str[0])) | ||
103 | { | ||
104 | if(strlen(str) < 32) | ||
105 | return false; | ||
106 | for(int j = 0; j < 16; j++) | ||
107 | { | ||
108 | byte a, b; | ||
109 | if(convxdigit(str[2 * j], &a) || convxdigit(str[2 * j + 1], &b)) | ||
110 | return false; | ||
111 | key->u.key[j] = (a << 4) | b; | ||
112 | } | ||
113 | /* skip key */ | ||
114 | *pstr = str + 32; | ||
115 | key->method = CRYPTO_KEY; | ||
116 | return true; | ||
117 | } | ||
118 | else | ||
119 | { | ||
120 | const char *prefix = "usbotp("; | ||
121 | if(strlen(str) < strlen(prefix)) | ||
122 | return false; | ||
123 | if(strncmp(str, prefix, strlen(prefix)) != 0) | ||
124 | return false; | ||
125 | str += strlen(prefix); | ||
126 | /* vid */ | ||
127 | long vid = strtol(str, &str, 16); | ||
128 | if(vid < 0 || vid > 0xffff) | ||
129 | return false; | ||
130 | if(*str++ != ':') | ||
131 | return false; | ||
132 | /* pid */ | ||
133 | long pid = strtol(str, &str, 16); | ||
134 | if(pid < 0 || pid > 0xffff) | ||
135 | return false; | ||
136 | if(*str++ != ')') | ||
137 | return false; | ||
138 | *pstr = str; | ||
139 | key->method = CRYPTO_USBOTP; | ||
140 | key->u.vid_pid = vid << 16 | pid; | ||
141 | return true; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | void add_keys(key_array_t ka, int kac) | ||
146 | { | ||
147 | key_array_t new_ka = xmalloc((g_nr_keys + kac) * sizeof(struct crypto_key_t)); | ||
148 | memcpy(new_ka, g_key_array, g_nr_keys * sizeof(struct crypto_key_t)); | ||
149 | memcpy(new_ka + g_nr_keys, ka, kac * sizeof(struct crypto_key_t)); | ||
150 | free(g_key_array); | ||
151 | g_key_array = new_ka; | ||
152 | g_nr_keys += kac; | ||
153 | } | ||
154 | |||
155 | void clear_keys() | ||
156 | { | ||
157 | free(g_key_array); | ||
158 | g_nr_keys = 0; | ||
159 | } | ||
160 | |||
161 | void add_keys_from_file(const char *key_file) | ||
162 | { | ||
163 | int size; | ||
164 | FILE *fd = fopen(key_file, "r"); | ||
165 | if(fd == NULL) | ||
166 | bug("opening key file failed"); | ||
167 | fseek(fd, 0, SEEK_END); | ||
168 | size = ftell(fd); | ||
169 | fseek(fd, 0, SEEK_SET); | ||
170 | char *buf = xmalloc(size + 1); | ||
171 | if(fread(buf, 1, size, fd) != (size_t)size) | ||
172 | bug("reading key file"); | ||
173 | buf[size] = 0; | ||
174 | fclose(fd); | ||
175 | |||
176 | if(g_debug) | ||
177 | printf("Parsing key file '%s'...\n", key_file); | ||
178 | char *p = buf; | ||
179 | while(1) | ||
180 | { | ||
181 | struct crypto_key_t k; | ||
182 | /* parse key */ | ||
183 | if(!parse_key(&p, &k)) | ||
184 | bug("invalid key file"); | ||
185 | if(g_debug) | ||
186 | { | ||
187 | printf("Add key: "); | ||
188 | print_key(&k, true); | ||
189 | } | ||
190 | add_keys(&k, 1); | ||
191 | /* request at least one space character before next key, or end of file */ | ||
192 | if(*p != 0 && !isspace(*p)) | ||
193 | bug("invalid key file"); | ||
194 | /* skip whitespace */ | ||
195 | while(isspace(*p)) | ||
196 | p++; | ||
197 | if(*p == 0) | ||
198 | break; | ||
199 | } | ||
200 | free(buf); | ||
201 | } | ||
202 | |||
203 | void print_hex(byte *data, int len, bool newline) | ||
204 | { | ||
205 | for(int i = 0; i < len; i++) | ||
206 | printf("%02X ", data[i]); | ||
207 | if(newline) | ||
208 | printf("\n"); | ||
209 | } | ||
210 | |||
211 | void print_key(struct crypto_key_t *key, bool newline) | ||
212 | { | ||
213 | switch(key->method) | ||
214 | { | ||
215 | case CRYPTO_KEY: | ||
216 | print_hex(key->u.key, 16, false); | ||
217 | break; | ||
218 | case CRYPTO_USBOTP: | ||
219 | printf("USB-OTP(%04x:%04x)", key->u.vid_pid >> 16, key->u.vid_pid & 0xffff); | ||
220 | break; | ||
221 | case CRYPTO_NONE: | ||
222 | printf("none"); | ||
223 | break; | ||
224 | } | ||
225 | if(newline) | ||
226 | printf("\n"); | ||
227 | } | ||
228 | |||
229 | char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' }; | ||
230 | |||
231 | char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' }; | ||
232 | char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' }; | ||
233 | char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' }; | ||
234 | char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' }; | ||
235 | char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' }; | ||
236 | |||
237 | static bool g_color_enable = true; | ||
238 | |||
239 | void enable_color(bool enable) | ||
240 | { | ||
241 | g_color_enable = enable; | ||
242 | } | ||
243 | |||
244 | void color(color_t c) | ||
245 | { | ||
246 | if(g_color_enable) | ||
247 | printf("%s", (char *)c); | ||
248 | } | ||