ps3dm_sm: set_del_encdec_key: fixed description for default key
[ps3dm-utils.git] / ps3dm_usb_dongle_auth.c
blob037e1e683405a81c59e7b9f197507b31a90f470f
2 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; version 2 of the License.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <getopt.h>
21 #include <errno.h>
23 #include <openssl/hmac.h>
24 #include <openssl/evp.h>
26 #include "ps3dm_proxy.h"
27 #include "ps3dm.h"
28 #include "ps3ss.h"
30 #define PS3DM_USB_DONGLE_AUTH_VERSION "0.0.1"
32 #define PS3DM_USB_DONGLE_AUTH_LAID 0x1070000002000001ull
33 #define PS3DM_USB_DONGLE_AUTH_PAID 0x1070000044000001ull
35 struct opts
37 char *device_name;
38 char *cmd;
39 int do_help;
40 int do_verbose;
41 int do_version;
44 static struct option long_opts[] = {
45 { "help", no_argument, NULL, 'h' },
46 { "verbose", no_argument, NULL, 'v' },
47 { "version", no_argument, NULL, 'V' },
48 { NULL, 0, NULL, 0 }
51 static uint8_t usb_dongle_master_key[] = {
52 0x46, 0xdc, 0xea, 0xd3, 0x17, 0xfe, 0x45, 0xd8, 0x09, 0x23,
53 0xeb, 0x97, 0xe4, 0x95, 0x64, 0x10, 0xd4, 0xcd, 0xb2, 0xc2
57 * usage
59 static void usage(void) {
60 fprintf(stderr,
61 "Usage: ps3dm_usb_dongle_auth [OPTIONS] DEVICE COMMAND [ARGS]\n"
62 "\n"
63 "Options:\n"
64 " -h, --help Show this message and exit\n"
65 " -v, --verbose Increase verbosity\n"
66 " -V, --version Show version information and exit\n"
67 "Commands:\n"
68 " gen_challenge Generates challenge\n"
69 " verify_resp DONGLEID RESPONSE Verifies response\n"
70 " gen_resp DONGLEID CHALLENGE Generates valid response for challenge\n"
71 "\n\n"
72 "Simple example: Generate challenge:\n"
73 " ps3dm_usb_dongle_auth /dev/ps3dmproxy gen_challenge\n");
77 * version
79 static void version(void)
81 fprintf(stderr,
82 "ps3dm_usb_dongle_auth " PS3DM_USB_DONGLE_AUTH_VERSION "\n"
83 "Copyright (C) 2011 graf_chokolo <grafchokolo@googlemail.com>\n"
84 "This is free software. You may redistribute copies of it "
85 "under the terms of\n"
86 "the GNU General Public License 2 "
87 "<http://www.gnu.org/licenses/gpl2.html>.\n"
88 "There is NO WARRANTY, to the extent permitted by law.\n");
92 * process_opts
94 static int process_opts(int argc, char **argv, struct opts *opts)
96 int c;
98 while ((c = getopt_long(argc, argv, "hvV", long_opts, NULL)) != -1) {
99 switch (c) {
100 case 'h':
101 case '?':
102 opts->do_help = 1;
103 return 0;
105 case 'v':
106 opts->do_verbose++;
107 break;
109 case 'V':
110 opts->do_version = 1;
111 return 0;
113 default:
114 fprintf(stderr, "Invalid command option: %c\n", c);
115 return -1;
119 if (optind >= argc) {
120 fprintf(stderr, "No device specified\n");
121 return -1;
124 opts->device_name = argv[optind];
125 optind++;
127 if (optind >= argc) {
128 fprintf(stderr, "No command specified\n");
129 return -1;
132 opts->cmd = argv[optind];
133 optind++;
135 return 0;
139 * cmd_gen_challenge
141 static int cmd_gen_challenge(int fd, struct opts *opts, int argc, char **argv)
143 uint8_t buf[128];
144 struct ps3dm_hdr *dm_hdr;
145 struct ps3ss_hdr *ss_hdr;
146 struct ps3ss_usb_dongle_auth_gen_challenge *ss_usb_dongle_auth_gen_challenge;
147 int error, i;
149 memset(buf, 0, sizeof(buf));
150 dm_hdr = (struct ps3dm_hdr *) buf;
151 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
152 ss_usb_dongle_auth_gen_challenge = (struct ps3ss_usb_dongle_auth_gen_challenge *)(ss_hdr + 1);
154 dm_hdr->request_id = 1;
155 dm_hdr->function_id = PS3SS_FID_USB_DONGLE_AUTH;
156 dm_hdr->request_size = PS3SS_HDR_SIZE;
157 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_usb_dongle_auth_gen_challenge);
159 ss_hdr->packet_id = PS3SS_PID_USB_DONGLE_AUTH_GEN_CHALLENGE;
160 ss_hdr->function_id = PS3SS_FID_USB_DONGLE_AUTH;
161 ss_hdr->laid = PS3DM_USB_DONGLE_AUTH_LAID;
162 ss_hdr->paid = PS3DM_USB_DONGLE_AUTH_PAID;
164 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
165 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
167 if (error) {
168 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
169 } else if (ss_hdr->retval != 0) {
170 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
171 } else {
172 if (opts->do_verbose) {
173 fprintf(stdout, "Challenge header:\n");
175 for (i = 0; i < sizeof(ss_usb_dongle_auth_gen_challenge->header); i++)
176 fprintf(stdout, "0x%02x ", ss_usb_dongle_auth_gen_challenge->header[i]);
178 fprintf(stdout, "\n");
181 for (i = 0; i < sizeof(ss_usb_dongle_auth_gen_challenge->challenge); i++)
182 fprintf(stdout, "0x%02x ", ss_usb_dongle_auth_gen_challenge->challenge[i]);
184 fprintf(stdout, "\n");
187 return error;
191 * cmd_verify_resp
193 static int cmd_verify_resp(int fd, struct opts *opts, int argc, char **argv)
195 uint32_t dongle_id, val;
196 uint8_t response[20];
197 int response_size = 0;
198 char *endptr;
199 uint8_t buf[128];
200 struct ps3dm_hdr *dm_hdr;
201 struct ps3ss_hdr *ss_hdr;
202 struct ps3ss_usb_dongle_auth_verify_resp *ss_usb_dongle_auth_verify_resp;
203 int error;
205 if (optind >= argc) {
206 fprintf(stderr, "No dongle id specified\n");
207 return -1;
210 dongle_id = strtoul(argv[optind], &endptr, 0);
211 if ((*endptr != '\0') || (dongle_id > 0xffff)) {
212 fprintf(stderr, "Invalid dongle id specified: %s\n", argv[optind]);
213 return -1;
216 optind++;
218 while (optind < argc) {
219 val = strtoul(argv[optind], &endptr, 0);
220 if ((*endptr != '\0') || (val > 0xff)) {
221 fprintf(stderr, "Invalid response specified: %s\n", argv[optind]);
222 return -1;
225 optind++;
227 response[response_size++] = val;
229 if (response_size == 20)
230 break;
233 if (response_size < 20) {
234 fprintf(stderr, "Response should be of size 20 bytes\n");
235 return -1;
238 memset(buf, 0, sizeof(buf));
239 dm_hdr = (struct ps3dm_hdr *) buf;
240 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
241 ss_usb_dongle_auth_verify_resp = (struct ps3ss_usb_dongle_auth_verify_resp *)(ss_hdr + 1);
243 dm_hdr->request_id = 1;
244 dm_hdr->function_id = PS3SS_FID_USB_DONGLE_AUTH;
245 dm_hdr->request_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_usb_dongle_auth_verify_resp);
246 dm_hdr->response_size = PS3SS_HDR_SIZE;
248 ss_hdr->packet_id = PS3SS_PID_USB_DONGLE_AUTH_VERIFY_RESP;
249 ss_hdr->function_id = PS3SS_FID_USB_DONGLE_AUTH;
250 ss_hdr->laid = PS3DM_USB_DONGLE_AUTH_LAID;
251 ss_hdr->paid = PS3DM_USB_DONGLE_AUTH_PAID;
253 ss_usb_dongle_auth_verify_resp->header[0] = 0x2e;
254 ss_usb_dongle_auth_verify_resp->header[1] = 0x02;
255 ss_usb_dongle_auth_verify_resp->header[2] = 0x02;
256 ss_usb_dongle_auth_verify_resp->dongle_id = dongle_id;
257 memcpy(ss_usb_dongle_auth_verify_resp->response, response, sizeof(response));
259 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
260 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
262 if (error)
263 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
264 else
265 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
267 return error;
271 * cmd_gen_resp
273 static int cmd_gen_resp(int fd, struct opts *opts, int argc, char **argv)
275 uint32_t val;
276 uint16_t dongle_id;
277 uint8_t challenge[20], dongle_key[20], response[20];
278 int challenge_size = 0;
279 char *endptr;
280 int i;
282 if (optind >= argc) {
283 fprintf(stderr, "No dongle id specified\n");
284 return -1;
287 val = strtoul(argv[optind], &endptr, 0);
288 if ((*endptr != '\0') || (val > 0xffff)) {
289 fprintf(stderr, "Invalid dongle id specified: %s\n", argv[optind]);
290 return -1;
293 dongle_id = val;
294 optind++;
296 while (optind < argc) {
297 val = strtoul(argv[optind], &endptr, 0);
298 if ((*endptr != '\0') || (val > 0xff)) {
299 fprintf(stderr, "Invalid challenge specified: %s\n", argv[optind]);
300 return -1;
303 optind++;
305 challenge[challenge_size++] = val;
307 if (challenge_size == 20)
308 break;
311 if (challenge_size < 20) {
312 fprintf(stderr, "Challenge should be of size 20 bytes\n");
313 return -1;
316 HMAC(EVP_sha1(), usb_dongle_master_key, sizeof(usb_dongle_master_key),
317 (uint8_t *) &dongle_id, sizeof(dongle_id), dongle_key, NULL);
319 if (opts->do_verbose) {
320 fprintf(stdout, "USB dongle key:\n");
322 for (i = 0; i < sizeof(dongle_key); i++)
323 fprintf(stdout, "0x%02x ", dongle_key[i]);
325 fprintf(stdout, "\n");
328 HMAC(EVP_sha1(), dongle_key, sizeof(dongle_key),
329 challenge, sizeof(challenge), response, NULL);
331 for (i = 0; i < sizeof(response); i++)
332 fprintf(stdout, "0x%02x ", response[i]);
334 fprintf(stdout, "\n");
336 return 0;
340 * main
342 int main(int argc, char **argv)
344 struct opts opts;
345 int fd = 0, error = 0;
347 memset(&opts, 0, sizeof(opts));
349 if (process_opts(argc, argv, &opts)) {
350 usage();
351 error = 1;
352 goto done;
355 if (opts.do_help) {
356 usage();
357 goto done;
358 } else if (opts.do_version) {
359 version();
360 goto done;
363 fd = ps3dm_proxy_open(opts.device_name);
364 if (fd < 0) {
365 fprintf(stderr, "%s: %s\n", opts.device_name, strerror(errno));
366 error = 2;
367 goto done;
370 if (!strcmp(opts.cmd, "gen_challenge")) {
371 error = cmd_gen_challenge(fd, &opts, argc, argv);
372 } else if (!strcmp(opts.cmd, "verify_resp")) {
373 error = cmd_verify_resp(fd, &opts, argc, argv);
374 } else if (!strcmp(opts.cmd, "gen_resp")) {
375 error = cmd_gen_resp(fd, &opts, argc, argv);
376 } else {
377 usage();
378 error = 1;
379 goto done;
382 if (error)
383 error = 3;
385 done:
387 if (fd >= 0)
388 ps3dm_proxy_close(fd);
390 exit(error);