Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1/*
2 * Copyright 2015-2018 Yubico AB
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <ctype.h>
18#include <stdbool.h>
19#include <stddef.h>
20#include <stdint.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <ykyh.h>
25
26#include <openssl/evp.h>
27
28#include "parsing.h"
29
30#include "cmdline.h"
31
32static bool hex_decode(const char *hex_in, size_t in_len, uint8_t *hex_out,
33 size_t *out_len) {
34 const char hex_translate[] = "0123456789abcdef";
35 bool first = true;
36
37 if (*out_len < in_len / 2) {
38 fprintf(stderr, "Unable to decode hex, buffer too small\n");
39 return false;
40 } else if (in_len % 2 != 0) {
41 fprintf(stderr, "Unable to decode hex, wrong length\n");
42 return false;
43 }
44
45 *out_len = in_len / 2;
46 for (size_t i = 0; i < in_len; i++) {
47 char *ind_ptr = strchr(hex_translate, tolower(*hex_in++));
48 int index = 0;
49 if (ind_ptr) {
50 index = ind_ptr - hex_translate;
51 } else {
52 fprintf(stderr, "Unable to decode hex, invalid character\n");
53 return false;
54 }
55
56 if (first) {
57 *hex_out = index << 4;
58 } else {
59 *hex_out++ |= index;
60 }
61 first = !first;
62 }
63
64 return true;
65}
66
67static bool parse_name(const char *prompt, char *name, char *parsed,
68 size_t *parsed_len) {
69 if (strlen(name) > *parsed_len) {
70 fprintf(stdout, "Unable to read name, buffer too small\n");
71 return false;
72 }
73
74 if (strlen(name) == 0) {
75 if (read_string(prompt, parsed, *parsed_len, false) == false) {
76 return false;
77 }
78 } else {
79 strncpy(parsed, name, strlen(name));
80 }
81
82 *parsed_len = strlen(name);
83
84 return true;
85}
86
87static bool parse_key(const char *prompt, char *key, uint8_t *parsed,
88 size_t *parsed_len) {
89 char buf[128];
90 size_t buf_size = sizeof(buf);
91
92 if (strlen(key) > buf_size) {
93 fprintf(stdout, "Unable to read key, buffer too small\n");
94 return false;
95 }
96
97 if (strlen(key) == 0) {
98 if (read_string(prompt, buf, buf_size, true) == false) {
99 return false;
100 }
101 buf_size = strlen(buf);
102 } else {
103 memcpy(buf, key, strlen(key));
104 buf_size = strlen(key);
105 }
106
107 if (hex_decode(buf, buf_size, parsed, parsed_len) == false) {
108 return false;
109 }
110
111 if (*parsed_len != YKYH_KEY_LEN) {
112 fprintf(stdout, "Unable to read key, wrong length (must be %d)\n",
114 return false;
115 }
116
117 return true;
118}
119
120static bool parse_touch_policy(enum enum_touch touch_policy,
121 uint8_t *touch_policy_parsed) {
122
123 switch (touch_policy) {
124 case touch__NULL:
125 case touch_arg_off:
126 *touch_policy_parsed = 0;
127 break;
128
129 case touch_arg_on:
130 *touch_policy_parsed = 1;
131 break;
132 }
133
134 return true;
135}
136
137static bool delete_credential(ykyh_state *state, char *name) {
138 ykyh_rc ykyhrc;
139 char name_parsed[YKYH_MAX_NAME_LEN + 2] = {0};
140 size_t name_parsed_len = sizeof(name_parsed);
141
142 if (parse_name("Name", name, name_parsed, &name_parsed_len) == false) {
143 return false;
144 }
145
146 ykyhrc = ykyh_delete(state, name_parsed);
147 if (ykyhrc != YKYHR_SUCCESS) {
148 fprintf(stderr, "Unable to delete credential: %s\n", ykyh_strerror(ykyhrc));
149 return false;
150 }
151
152 fprintf(stdout, "Credential successfully deleted\n");
153
154 return true;
155}
156
157static bool list_credentials(ykyh_state *state) {
158 ykyh_rc ykyhrc;
159 ykyh_list_entry list[32];
160 size_t list_items = sizeof(list) / sizeof(list[0]);
161
162 ykyhrc = ykyh_list_keys(state, list, &list_items);
163 if (ykyhrc != YKYHR_SUCCESS) {
164 fprintf(stderr, "Unable to list credentials: %s\n", ykyh_strerror(ykyhrc));
165 return false;
166 }
167
168 if (list_items == 0) {
169 fprintf(stdout, "No items found\n");
170 return true;
171 }
172
173 for (size_t i = 0; i < list_items; i++) {
174 fprintf(stdout, "%d\t%d\t%s\n", list[i].algo, list[i].ctr, list[i].name);
175 }
176
177 return true;
178}
179
180static bool put_credential(ykyh_state *state, char *name,
181 char *derivation_password, char *key_enc,
182 char *key_mac, char *password,
183 enum enum_touch touch_policy) {
184 ykyh_rc ykyhrc;
185 char name_parsed[YKYH_MAX_NAME_LEN + 2] = {0};
186 size_t name_parsed_len = sizeof(name_parsed);
187 char dpw_parsed[256] = {0};
188 size_t dpw_parsed_len = sizeof(dpw_parsed);
189 uint8_t key_enc_parsed[YKYH_KEY_LEN];
190 size_t key_enc_parsed_len = sizeof(key_enc_parsed);
191 uint8_t key_mac_parsed[YKYH_KEY_LEN];
192 size_t key_mac_parsed_len = sizeof(key_mac_parsed);
193 char pw_parsed[YKYH_PW_LEN + 2] = {0};
194 size_t pw_parsed_len = sizeof(pw_parsed);
195 uint8_t touch_policy_parsed = 0;
196
197 if (parse_name("Name", name, name_parsed, &name_parsed_len) == false) {
198 return false;
199 }
200
201 if (strlen(key_mac) == 0 && strlen(key_enc) == 0) {
202 if (parse_pw("Derivation password", derivation_password, dpw_parsed,
203 &dpw_parsed_len) == false) {
204 return false;
205 }
206 } else {
207 dpw_parsed_len = 0;
208 }
209
210 if (dpw_parsed_len == 0) {
211 if (parse_key("Encryption key", key_enc, key_enc_parsed,
212 &key_enc_parsed_len) == false) {
213 return false;
214 }
215
216 if (parse_key("MAC key", key_mac, key_mac_parsed, &key_mac_parsed_len) ==
217 false) {
218 return false;
219 }
220 } else {
221 uint8_t key[YKYH_KEY_LEN * 2];
222 int ret = PKCS5_PBKDF2_HMAC((const char *) dpw_parsed, dpw_parsed_len,
225 EVP_sha256(), sizeof(key), key);
226
227 if (ret != 1) {
228 return false;
229 }
230
231 memcpy(key_enc_parsed, key, YKYH_KEY_LEN);
232 key_enc_parsed_len = YKYH_KEY_LEN;
233 memcpy(key_mac_parsed, key + YKYH_KEY_LEN, YKYH_KEY_LEN);
234 key_mac_parsed_len = YKYH_KEY_LEN;
235 }
236
237 if (parse_pw("Password", password, pw_parsed, &pw_parsed_len) == false) {
238 return false;
239 }
240
241 if (parse_touch_policy(touch_policy, &touch_policy_parsed) == false) {
242 return false;
243 }
244
245 ykyhrc = ykyh_put(state, name_parsed, key_enc_parsed, key_enc_parsed_len,
246 key_mac_parsed, key_mac_parsed_len, pw_parsed,
247 touch_policy_parsed);
248 if (ykyhrc != YKYHR_SUCCESS) {
249 fprintf(stderr, "Unable to store credential: %s\n", ykyh_strerror(ykyhrc));
250 return false;
251 }
252
253 fprintf(stdout, "Credential successfully stored\n");
254
255 return true;
256}
257
259 ykyh_rc ykyhrc;
260
261 ykyhrc = ykyh_reset(state);
262 if (ykyhrc != YKYHR_SUCCESS) {
263 fprintf(stderr, "Unable to reset device: %s\n", ykyh_strerror(ykyhrc));
264 return false;
265 }
266
267 fprintf(stdout, "Device successuflly reset\n");
268
269 return true;
270}
271
273 ykyh_rc ykyhrc;
274 char version[64];
275 size_t version_len = sizeof(version);
276
277 ykyhrc = ykyh_get_version(state, version, version_len);
278 if (ykyhrc != YKYHR_SUCCESS) {
279 fprintf(stderr, "Unable to get version: %s\n", ykyh_strerror(ykyhrc));
280 return false;
281 }
282
283 fprintf(stdout, "Version %s\n", version);
284
285 return true;
286}
287
288int main(int argc, char *argv[]) {
289 struct gengetopt_args_info args_info;
290 ykyh_state *state = NULL;
291 ykyh_rc ykyhrc;
292
293 int rc = EXIT_FAILURE;
294
295 if (cmdline_parser(argc, argv, &args_info) != 0) {
296 goto main_exit;
297 }
298
299 ykyhrc = ykyh_init(&state, args_info.verbose_arg);
300 if (ykyhrc != YKYHR_SUCCESS) {
301 fprintf(stderr, "Failed to initialize libykyh\n");
302 goto main_exit;
303 }
304
305 ykyhrc = ykyh_connect(state, args_info.reader_arg);
306 if (ykyhrc != YKYHR_SUCCESS) {
307 fprintf(stderr, "Unable to connect: %s\n", ykyh_strerror(ykyhrc));
308 goto main_exit;
309 }
310
311 bool result = false;
312 switch (args_info.action_arg) {
313 case action_arg_delete:
314 result = delete_credential(state, args_info.name_arg);
315 break;
316
317 case action_arg_list:
318 result = list_credentials(state);
319 break;
320
321 case action_arg_put:
322 result = put_credential(state, args_info.name_arg,
323 args_info.derivation_password_arg,
324 args_info.enckey_arg, args_info.mackey_arg,
325 args_info.password_arg, args_info.touch_arg);
326 break;
327
328 case action_arg_reset:
329 result = reset_device(state);
330 break;
331
332 case action_arg_version:
333 result = get_version(state);
334 break;
335
336 case action__NULL:
337 fprintf(stderr, "No action given, nothing to do\n");
338 break;
339 }
340
341 if (result == true) {
342 rc = EXIT_SUCCESS;
343 }
344
345main_exit:
346
348
349 return rc;
350}
std::string name
char ** argv
bool read_string(const char *name, char *str_buf, size_t str_buf_len, bool hidden)
Definition parsing.c:26
bool parse_pw(const char *prompt, char *pw, char *parsed, size_t *parsed_len)
Definition parsing.c:61
unsigned char uint8_t
Definition stdint.h:124
Definition ykyh.h:86
bool hex_decode(const char *in, uint8_t *out, size_t *len)
Definition util.c:524
bool get_version(ykyh_state *state)
Definition main.c:272
bool reset_device(ykyh_state *state)
Definition main.c:258
const char * ykyh_strerror(ykyh_rc err)
Definition error.c:40
ykyh_rc ykyh_put(ykyh_state *state, const char *name, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, const char *pw, const uint8_t touch_policy)
Definition ykyh.c:289
ykyh_rc ykyh_get_version(ykyh_state *state, char *version, size_t len)
Definition ykyh.c:260
ykyh_rc ykyh_done(ykyh_state *state)
Definition ykyh.c:64
ykyh_rc ykyh_connect(ykyh_state *state, const char *wanted)
Definition ykyh.c:92
ykyh_rc ykyh_list_keys(ykyh_state *state, ykyh_list_entry *list, size_t *list_items)
Definition ykyh.c:510
ykyh_rc ykyh_reset(ykyh_state *state)
Definition ykyh.c:483
ykyh_rc ykyh_init(ykyh_state **state, int verbose)
Definition ykyh.c:35
ykyh_rc ykyh_delete(ykyh_state *state, char *name)
Definition ykyh.c:364
#define YKYH_PW_LEN
Definition ykyh.h:67
#define YKYH_DEFAULT_ITERS
Definition ykyh.h:72
ykyh_rc
Definition ykyh.h:76
@ YKYHR_SUCCESS
Definition ykyh.h:77
#define YKYH_KEY_LEN
Definition ykyh.h:66
#define YKYH_DEFAULT_SALT
Definition ykyh.h:71
#define YKYH_MAX_NAME_LEN
Definition ykyh.h:65
CK_RV ret
size_t out_len
uint8_t buf[2048]
yh_rc rc
memcpy((char *) pInfo->slotDescription, s, l)
size_t in_len