ps3dm_sm: set_del_encdec_key: fixed description for default key
[ps3dm-utils.git] / ps3dm_sm.c
blob920ff34b49560e232eda7327d695f57d22f434c9
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 "ps3dm_proxy.h"
24 #include "ps3dm.h"
25 #include "ps3ss.h"
27 #define PS3DM_SM_VERSION "0.0.1"
29 #define PS3DM_SM_LAID 0x1070000002000001ull
30 #define PS3DM_SM_GET_RND_NUMBER_PAID 0x1070000031000001ull
31 #define PS3DM_SM_PAID 0x10700003ff000001ull
33 struct opts
35 char *device_name;
36 char *cmd;
37 int do_help;
38 int do_verbose;
39 int do_version;
42 static struct option long_opts[] = {
43 { "help", no_argument, NULL, 'h' },
44 { "verbose", no_argument, NULL, 'v' },
45 { "version", no_argument, NULL, 'V' },
46 { NULL, 0, NULL, 0 }
50 * usage
52 static void usage(void) {
53 fprintf(stderr,
54 "Usage: ps3dm_sm [OPTIONS] DEVICE COMMAND [ARGS]\n"
55 "\n"
56 "Options:\n"
57 " -h, --help Show this message and exit\n"
58 " -v, --verbose Increase verbosity\n"
59 " -V, --version Show version information and exit\n"
60 "Commands:\n"
61 " set_encdec_key KEY KEYSIZE Sets ENCDEC/ATA key\n"
62 " set_del_encdec_key PARAM Sets/Deletes ENCDEC/ATA key\n"
63 " PARAM:\n"
64 " 0xC-0xF Deletes ENCDEC/ATA key\n"
65 " 0x10[0-F] Sets default ENCDEC/ATA key\n"
66 " 0x11[0-F] Deletes default ENCDEC/ATA key\n"
67 " get_rnd_number Returns random number\n"
68 " drive_auth PARAM Authenticates BD drive\n"
69 " PARAM:\n"
70 " 0x29 Authenticates BD drive\n"
71 " 0x46 Resets BD drive\n"
72 " ps2_disc_auth PARAM Authenticates PS2 disc\n"
73 " get_version Returns version\n"
74 " drive_ctrl PARAM Controls BD drive\n"
75 "\n\n"
76 "Simple example: Get random number:\n"
77 " ps3dm_sm /dev/ps3dmproxy get_rnd_number\n");
81 * version
83 static void version(void)
85 fprintf(stderr,
86 "ps3dm_sm " PS3DM_SM_VERSION "\n"
87 "Copyright (C) 2011 graf_chokolo <grafchokolo@googlemail.com>\n"
88 "This is free software. You may redistribute copies of it "
89 "under the terms of\n"
90 "the GNU General Public License 2 "
91 "<http://www.gnu.org/licenses/gpl2.html>.\n"
92 "There is NO WARRANTY, to the extent permitted by law.\n");
96 * process_opts
98 static int process_opts(int argc, char **argv, struct opts *opts)
100 int c;
102 while ((c = getopt_long(argc, argv, "hvV", long_opts, NULL)) != -1) {
103 switch (c) {
104 case 'h':
105 case '?':
106 opts->do_help = 1;
107 return 0;
109 case 'v':
110 opts->do_verbose++;
111 break;
113 case 'V':
114 opts->do_version = 1;
115 return 0;
117 default:
118 fprintf(stderr, "Invalid command option: %c\n", c);
119 return -1;
123 if (optind >= argc) {
124 fprintf(stderr, "No device specified\n");
125 return -1;
128 opts->device_name = argv[optind];
129 optind++;
131 if (optind >= argc) {
132 fprintf(stderr, "No command specified\n");
133 return -1;
136 opts->cmd = argv[optind];
137 optind++;
139 return 0;
143 * cmd_set_encdec_key
145 static int cmd_set_encdec_key(int fd, struct opts *opts, int argc, char **argv)
147 uint32_t val;
148 uint8_t key[24];
149 uint64_t key_size;
150 char *endptr;
151 uint8_t buf[256];
152 struct ps3dm_hdr *dm_hdr;
153 struct ps3ss_hdr *ss_hdr;
154 struct ps3ss_sm_set_encdec_key *ss_sm_set_encdec_key;
155 int error;
157 if (optind >= argc) {
158 fprintf(stderr, "No key specified\n");
159 return -1;
162 key_size = 0;
164 while (optind < argc) {
165 val = strtoul(argv[optind], &endptr, 0);
166 if ((*endptr != '\0') || (val > 0xff)) {
167 fprintf(stderr, "Invalid key specified: %s\n", argv[optind]);
168 return -1;
171 optind++;
173 key[key_size++] = val;
175 if (key_size == 24)
176 break;
179 if (key_size < 24) {
180 fprintf(stderr, "Key should be of size 24 bytes\n");
181 return -1;
184 if (optind >= argc) {
185 fprintf(stderr, "No key length specified\n");
186 return -1;
189 key_size = strtoull(argv[optind], &endptr, 0);
190 if (*endptr != '\0') {
191 fprintf(stderr, "Invalid key length specified: %s\n", argv[optind]);
192 return -1;
195 optind++;
197 memset(buf, 0, sizeof(buf));
198 dm_hdr = (struct ps3dm_hdr *) buf;
199 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
200 ss_sm_set_encdec_key = (struct ps3ss_sm_set_encdec_key *)(ss_hdr + 1);
202 dm_hdr->request_id = 1;
203 dm_hdr->function_id = PS3SS_FID_SM;
204 dm_hdr->request_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_set_encdec_key);
205 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_set_encdec_key);
207 ss_hdr->packet_id = PS3SS_PID_SM_SET_ENCDEC_KEY;
208 ss_hdr->function_id = PS3SS_FID_SM;
209 ss_hdr->laid = PS3DM_SM_LAID;
210 ss_hdr->paid = PS3DM_SM_PAID;
212 memcpy(ss_sm_set_encdec_key->key, key, sizeof(key));
213 ss_sm_set_encdec_key->key_size = key_size;
215 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
216 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
218 if (error) {
219 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
220 return error;
221 } else if (ss_hdr->retval) {
222 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
223 error = -1;
224 } else {
225 fprintf(stdout, "0x%016lx\n", ss_sm_set_encdec_key->param);
228 return error;
232 * cmd_set_del_encdec_key
234 static int cmd_set_del_encdec_key(int fd, struct opts *opts, int argc, char **argv)
236 uint64_t param;
237 char *endptr;
238 uint8_t buf[128];
239 struct ps3dm_hdr *dm_hdr;
240 struct ps3ss_hdr *ss_hdr;
241 struct ps3ss_sm_set_del_encdec_key *ss_sm_set_del_encdec_key;
242 int error;
244 if (optind >= argc) {
245 fprintf(stderr, "No parameter specified\n");
246 return -1;
249 param = strtoull(argv[optind], &endptr, 0);
250 if (*endptr != '\0') {
251 fprintf(stderr, "Invalid parameter specified: %s\n", argv[optind]);
252 return -1;
255 optind++;
257 memset(buf, 0, sizeof(buf));
258 dm_hdr = (struct ps3dm_hdr *) buf;
259 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
260 ss_sm_set_del_encdec_key = (struct ps3ss_sm_set_del_encdec_key *)(ss_hdr + 1);
262 dm_hdr->request_id = 1;
263 dm_hdr->function_id = PS3SS_FID_SM;
264 dm_hdr->request_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_set_del_encdec_key);
265 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_set_del_encdec_key);
267 ss_hdr->packet_id = PS3SS_PID_SM_SET_DEL_ENCDEC_KEY;
268 ss_hdr->function_id = PS3SS_FID_SM;
269 ss_hdr->laid = PS3DM_SM_LAID;
270 ss_hdr->paid = PS3DM_SM_PAID;
272 ss_sm_set_del_encdec_key->param = param;
274 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
275 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
277 if (error) {
278 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
279 return error;
282 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
284 return error;
288 * cmd_get_rnd_number
290 static int cmd_get_rnd_number(int fd, struct opts *opts, int argc, char **argv)
292 uint8_t buf[128];
293 struct ps3dm_hdr *dm_hdr;
294 struct ps3ss_hdr *ss_hdr;
295 struct ps3ss_sm_get_rnd_number *ss_sm_get_rnd_number;
296 int error, i;
298 memset(buf, 0, sizeof(buf));
299 dm_hdr = (struct ps3dm_hdr *) buf;
300 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
301 ss_sm_get_rnd_number = (struct ps3ss_sm_get_rnd_number *)(ss_hdr + 1);
303 dm_hdr->request_id = 1;
304 dm_hdr->function_id = PS3SS_FID_SM;
305 dm_hdr->request_size = PS3SS_HDR_SIZE;
306 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_get_rnd_number);
308 ss_hdr->packet_id = PS3SS_PID_SM_GET_RND_NUMBER;
309 ss_hdr->function_id = PS3SS_FID_SM;
310 ss_hdr->laid = PS3DM_SM_LAID;
311 ss_hdr->paid = PS3DM_SM_GET_RND_NUMBER_PAID;
313 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
314 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
316 if (error) {
317 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
318 } else if (ss_hdr->retval) {
319 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
320 } else {
321 for (i = 0; i < sizeof(ss_sm_get_rnd_number->field0); i++)
322 fprintf(stdout, "0x%02x ", ss_sm_get_rnd_number->field0[i]);
324 fprintf(stdout, "\n");
327 return error;
331 * cmd_drive_auth
333 static int cmd_drive_auth(int fd, struct opts *opts, int argc, char **argv)
335 uint64_t param;
336 char *endptr;
337 uint8_t buf[128];
338 struct ps3dm_hdr *dm_hdr;
339 struct ps3ss_hdr *ss_hdr;
340 struct ps3ss_sm_drive_auth *ss_sm_drive_auth;
341 int error;
343 if (optind >= argc) {
344 fprintf(stderr, "No parameter specified\n");
345 return -1;
348 param = strtoull(argv[optind], &endptr, 0);
349 if (*endptr != '\0') {
350 fprintf(stderr, "Invalid parameter specified: %s\n", argv[optind]);
351 return -1;
354 optind++;
356 memset(buf, 0, sizeof(buf));
357 dm_hdr = (struct ps3dm_hdr *) buf;
358 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
359 ss_sm_drive_auth = (struct ps3ss_sm_drive_auth *)(ss_hdr + 1);
361 dm_hdr->request_id = 1;
362 dm_hdr->function_id = PS3SS_FID_SM;
363 dm_hdr->request_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_drive_auth);
364 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_drive_auth);
366 ss_hdr->packet_id = PS3SS_PID_SM_DRIVE_AUTH;
367 ss_hdr->function_id = PS3SS_FID_SM;
368 ss_hdr->laid = PS3DM_SM_LAID;
369 ss_hdr->paid = PS3DM_SM_PAID;
371 ss_sm_drive_auth->param = param;
373 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
374 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
376 if (error) {
377 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
378 return error;
381 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
383 return error;
387 * cmd_ps2_disc_auth
389 static int cmd_ps2_disc_auth(int fd, struct opts *opts, int argc, char **argv)
391 uint8_t buf[128];
392 struct ps3dm_hdr *dm_hdr;
393 struct ps3ss_hdr *ss_hdr;
394 struct ps3ss_sm_ps2_disc_auth *ss_sm_ps2_disc_auth;
395 int error, i;
397 memset(buf, 0, sizeof(buf));
398 dm_hdr = (struct ps3dm_hdr *) buf;
399 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
400 ss_sm_ps2_disc_auth = (struct ps3ss_sm_ps2_disc_auth *)(ss_hdr + 1);
402 dm_hdr->request_id = 1;
403 dm_hdr->function_id = PS3SS_FID_SM;
404 dm_hdr->request_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_ps2_disc_auth);
405 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_ps2_disc_auth);
407 ss_hdr->packet_id = PS3SS_PID_SM_PS2_DISC_AUTH;
408 ss_hdr->function_id = PS3SS_FID_SM;
409 ss_hdr->laid = PS3DM_SM_LAID;
410 ss_hdr->paid = PS3DM_SM_PAID;
412 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
413 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
415 if (error) {
416 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
417 } else if (ss_hdr->retval) {
418 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
419 error = -1;
420 } else {
421 for (i = 0; i < sizeof(ss_sm_ps2_disc_auth->field0); i++)
422 fprintf(stdout, "0x%02x ", ss_sm_ps2_disc_auth->field0[i]);
424 fprintf(stdout, "\n");
427 return error;
431 * cmd_get_version
433 static int cmd_get_version(int fd, struct opts *opts, int argc, char **argv)
435 uint8_t buf[128];
436 struct ps3dm_hdr *dm_hdr;
437 struct ps3ss_hdr *ss_hdr;
438 struct ps3ss_sm_get_version *ss_sm_get_version;
439 int error, i;
441 memset(buf, 0, sizeof(buf));
442 dm_hdr = (struct ps3dm_hdr *) buf;
443 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
444 ss_sm_get_version = (struct ps3ss_sm_get_version *)(ss_hdr + 1);
446 dm_hdr->request_id = 1;
447 dm_hdr->function_id = PS3SS_FID_SM;
448 dm_hdr->request_size = PS3SS_HDR_SIZE;
449 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_get_version);
451 ss_hdr->packet_id = PS3SS_PID_SM_GET_VERSION;
452 ss_hdr->function_id = PS3SS_FID_SM;
453 ss_hdr->laid = PS3DM_SM_LAID;
454 ss_hdr->paid = PS3DM_SM_PAID;
456 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
457 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
459 if (error) {
460 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
461 } else if (ss_hdr->retval) {
462 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
463 } else {
464 for (i = 0; i < sizeof(ss_sm_get_version->field0); i++)
465 fprintf(stdout, "0x%02x ", ss_sm_get_version->field0[i]);
467 fprintf(stdout, "\n");
470 return error;
474 * cmd_drive_ctrl
476 static int cmd_drive_ctrl(int fd, struct opts *opts, int argc, char **argv)
478 uint64_t param;
479 char *endptr;
480 uint8_t buf[128];
481 struct ps3dm_hdr *dm_hdr;
482 struct ps3ss_hdr *ss_hdr;
483 struct ps3ss_sm_drive_ctrl *ss_sm_drive_ctrl;
484 int error, i;
486 if (optind >= argc) {
487 fprintf(stderr, "No parameter specified\n");
488 return -1;
491 param = strtoull(argv[optind], &endptr, 0);
492 if (*endptr != '\0') {
493 fprintf(stderr, "Invalid parameter specified: %s\n", argv[optind]);
494 return -1;
497 optind++;
499 memset(buf, 0, sizeof(buf));
500 dm_hdr = (struct ps3dm_hdr *) buf;
501 ss_hdr = (struct ps3ss_hdr *)(dm_hdr + 1);
502 ss_sm_drive_ctrl = (struct ps3ss_sm_drive_ctrl *)(ss_hdr + 1);
504 dm_hdr->request_id = 1;
505 dm_hdr->function_id = PS3SS_FID_SM;
506 dm_hdr->request_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_drive_ctrl);
507 dm_hdr->response_size = PS3SS_HDR_SIZE + sizeof(struct ps3ss_sm_drive_ctrl);
509 ss_hdr->packet_id = PS3SS_PID_SM_DRIVE_CTRL;
510 ss_hdr->function_id = PS3SS_FID_SM;
511 ss_hdr->laid = PS3DM_SM_LAID;
512 ss_hdr->paid = PS3DM_SM_PAID;
514 ss_sm_drive_ctrl->param = param;
516 error = ps3dm_proxy_do_request(fd, dm_hdr, PS3DM_HDR_SIZE + dm_hdr->request_size,
517 dm_hdr, PS3DM_HDR_SIZE + dm_hdr->response_size);
519 if (error) {
520 fprintf(stderr, "%s: %s\n", opts->device_name, strerror(errno));
521 } else if (ss_hdr->retval) {
522 fprintf(stderr, "%s: SS retval %d\n", opts->device_name, ss_hdr->retval);
523 error = -1;
524 } else {
525 for (i = 0; i < sizeof(ss_sm_drive_ctrl->field8); i++)
526 fprintf(stdout, "0x%02x ", ss_sm_drive_ctrl->field8[i]);
528 fprintf(stdout, "\n");
531 return error;
535 * main
537 int main(int argc, char **argv)
539 struct opts opts;
540 int fd = 0, error = 0;
542 memset(&opts, 0, sizeof(opts));
544 if (process_opts(argc, argv, &opts)) {
545 usage();
546 error = 1;
547 goto done;
550 if (opts.do_help) {
551 usage();
552 goto done;
553 } else if (opts.do_version) {
554 version();
555 goto done;
558 fd = ps3dm_proxy_open(opts.device_name);
559 if (fd < 0) {
560 fprintf(stderr, "%s: %s\n", opts.device_name, strerror(errno));
561 error = 2;
562 goto done;
565 if (!strcmp(opts.cmd, "set_encdec_key")) {
566 error = cmd_set_encdec_key(fd, &opts, argc, argv);
567 } else if (!strcmp(opts.cmd, "set_del_encdec_key")) {
568 error = cmd_set_del_encdec_key(fd, &opts, argc, argv);
569 } else if (!strcmp(opts.cmd, "get_rnd_number")) {
570 error = cmd_get_rnd_number(fd, &opts, argc, argv);
571 } else if (!strcmp(opts.cmd, "drive_auth")) {
572 error = cmd_drive_auth(fd, &opts, argc, argv);
573 } else if (!strcmp(opts.cmd, "ps2_disc_auth")) {
574 error = cmd_ps2_disc_auth(fd, &opts, argc, argv);
575 } else if (!strcmp(opts.cmd, "get_version")) {
576 error = cmd_get_version(fd, &opts, argc, argv);
577 } else if (!strcmp(opts.cmd, "drive_ctrl")) {
578 error = cmd_drive_ctrl(fd, &opts, argc, argv);
579 } else {
580 usage();
581 error = 1;
582 goto done;
585 if (error)
586 error = 3;
588 done:
590 if (fd >= 0)
591 ps3dm_proxy_close(fd);
593 exit(error);