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
23 #include <openssl/hmac.h>
24 #include <openssl/evp.h>
26 #include "ps3dm_proxy.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
44 static struct option long_opts
[] = {
45 { "help", no_argument
, NULL
, 'h' },
46 { "verbose", no_argument
, NULL
, 'v' },
47 { "version", no_argument
, NULL
, 'V' },
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
59 static void usage(void) {
61 "Usage: ps3dm_usb_dongle_auth [OPTIONS] DEVICE COMMAND [ARGS]\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"
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"
72 "Simple example: Generate challenge:\n"
73 " ps3dm_usb_dongle_auth /dev/ps3dmproxy gen_challenge\n");
79 static void version(void)
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");
94 static int process_opts(int argc
, char **argv
, struct opts
*opts
)
98 while ((c
= getopt_long(argc
, argv
, "hvV", long_opts
, NULL
)) != -1) {
110 opts
->do_version
= 1;
114 fprintf(stderr
, "Invalid command option: %c\n", c
);
119 if (optind
>= argc
) {
120 fprintf(stderr
, "No device specified\n");
124 opts
->device_name
= argv
[optind
];
127 if (optind
>= argc
) {
128 fprintf(stderr
, "No command specified\n");
132 opts
->cmd
= argv
[optind
];
141 static int cmd_gen_challenge(int fd
, struct opts
*opts
, int argc
, char **argv
)
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
;
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
);
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
);
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");
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;
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
;
205 if (optind
>= argc
) {
206 fprintf(stderr
, "No dongle id specified\n");
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
]);
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
]);
227 response
[response_size
++] = val
;
229 if (response_size
== 20)
233 if (response_size
< 20) {
234 fprintf(stderr
, "Response should be of size 20 bytes\n");
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
);
263 fprintf(stderr
, "%s: %s\n", opts
->device_name
, strerror(errno
));
265 fprintf(stderr
, "%s: SS retval %d\n", opts
->device_name
, ss_hdr
->retval
);
273 static int cmd_gen_resp(int fd
, struct opts
*opts
, int argc
, char **argv
)
277 uint8_t challenge
[20], dongle_key
[20], response
[20];
278 int challenge_size
= 0;
282 if (optind
>= argc
) {
283 fprintf(stderr
, "No dongle id specified\n");
287 val
= strtoul(argv
[optind
], &endptr
, 0);
288 if ((*endptr
!= '\0') || (val
> 0xffff)) {
289 fprintf(stderr
, "Invalid dongle id specified: %s\n", argv
[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
]);
305 challenge
[challenge_size
++] = val
;
307 if (challenge_size
== 20)
311 if (challenge_size
< 20) {
312 fprintf(stderr
, "Challenge should be of size 20 bytes\n");
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");
342 int main(int argc
, char **argv
)
345 int fd
= 0, error
= 0;
347 memset(&opts
, 0, sizeof(opts
));
349 if (process_opts(argc
, argv
, &opts
)) {
358 } else if (opts
.do_version
) {
363 fd
= ps3dm_proxy_open(opts
.device_name
);
365 fprintf(stderr
, "%s: %s\n", opts
.device_name
, strerror(errno
));
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
);
388 ps3dm_proxy_close(fd
);