Editing Talk:BD Drive Reverse Engineering

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
= Getting keys the easier way =
= Getting keys the easier way =
== EID4 ==


First you need to get the sv_iso_spu_module.self individuals seed that can be found in the metadata header:  
First you need to get the sv_iso_spu_module.self individuals seed that can be found in the metadata header:  


  3E C2 0C 17 02 19 01 97 8A 29 71 79 38 29 D3 08
<pre>
  04 29 FA 84 E3 3E 7F 73 0C 1D 41 6E EA 25 CA FB
3E C2 XX XX XX XX XX XX XX XX XX XX XX XX XX XX
  3D E0 2B C0 05 EA 49 0B 03 E9 91 98 F8 3F 10 1F
04 29 XX XX XX XX XX XX XX XX XX XX XX XX XX XX
  1B A3 4B 50 58 94 28 AD D2 B3 EB 3F F4 C3 1A 58
3D E0 XX XX XX XX XX XX XX XX XX XX XX XX XX XX
1B A3 XX XX XX XX XX XX XX XX XX XX XX XX XX XX
</pre>


Using your console specific eid_root_key/iv (e.g. from metldr dump) and libeeid (insert the seed in keys.c) you can then decrypt EID4 directly by calling  
Using your console specific eid_root_key/iv (e.g. from metldr dump) and libeeid (insert the seed in keys.c) you can then decrypt EID4 directly by calling  


<syntaxhighlight lang="c">
<pre>
u8 eid4[0x30] = {/* your EID4 */};
u8 eid4[0x30] = {/* your EID4 */};
eid4_decrypt_buffer(eid4);
eid4_decrypt_buffer(eid4);
</syntaxhighlight>
</pre>


Now you got the two keys you need in eid4+0x00 and eid4+0x10 :)
Now you got the two keys you need in eid4+0x00 and eid4+0x10 :)
== EID2 ==
First you need to get the fdm_spu_module.self individuals seed that can be found in the metadata header:
  74 92 E5 7C 2C 7C 63 F4 49 42 26 8F B4 1C 58 ED
  66 83 41 F9 C9 7B 29 83 96 FA 9D 82 07 51 99 D8
  BC 1A 93 4B 37 4F A3 8D 46 AF 94 C7 C3 33 73 B3
  09 57 20 84 FE 2D E3 44 57 E0 F8 52 7A 34 75 3D
Using your console specific eid_root_key/iv (e.g. from metldr dump) and libeeid (insert the seed, key and IV in keys.c) you can then decrypt EID2 directly by calling
<syntaxhighlight lang="c">
u8 eid2[0x730] = {/* your EID2 */};
p_block = eid2_generate_block_buffer(p_block_enc, EID2_BLOCKTYPE_P);
s_block = eid2_generate_block_buffer(s_block_enc, EID2_BLOCKTYPE_S);
eid2_decrypt_block(p_block + 0x10, 0x60);
eid2_decrypt_block(s_block + 0x10, 0x670);
</syntaxhighlight>
= SACD ripper =
source: [http://sacd-ripper.googlecode.com/svn-history/r58/trunk/sacdread/sacd_lv2_storage.c]
<pre>
/* The generic packet command opcodes for CD/DVD Logical Units,
* From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
#define GPCMD_GET_CONFIGURATION     0x46
#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
#define GPCMD_MODE_SELECT_10     0x55
#define GPCMD_MODE_SENSE_10     0x5a
#define GPCMD_READ_CD     0xbe
#define GPCMD_READ_DVD_STRUCTURE     0xad
#define GPCMD_READ_TRACK_RZONE_INFO     0x52
#define GPCMD_READ_TOC_PMA_ATIP     0x43
#define GPCMD_REPORT_KEY     0xa4
#define GPCMD_SEND_KEY     0xa3
#define LV2_STORAGE_SEND_ATAPI_COMMAND (1)
struct lv2_atapi_cmnd_block {
    uint8_t pkt[32]; /* packet command block          */
    uint32_t pktlen; /* should be 12 for ATAPI 8020    */
    uint32_t blocks;
    uint32_t block_size;
    uint32_t proto; /* transfer mode                  */
    uint32_t in_out; /* transfer direction            */
    uint32_t unknown;
} __attribute__((packed));
typedef struct {
    int fd;
    uint64_t device_id;
    sys_ppu_thread_t thread_id;
    sys_mutex_t read_async_mutex_id;
    sys_event_queue_t queue;
int io_buffer;
int io_buffer_piece;
} sac_accessor_driver_t;
enum lv2_atapi_proto {
    NON_DATA_PROTO = 0,
    PIO_DATA_IN_PROTO = 1,
    PIO_DATA_OUT_PROTO = 2,
    DMA_PROTO = 3
};
enum lv2_atapi_in_out {
    DIR_WRITE = 0, /* memory -> device */
    DIR_READ = 1 /* device -> memory */
};
static inline void init_atapi_cmnd_block(
        struct lv2_atapi_cmnd_block *atapi_cmnd
        , uint32_t block_size
        , uint32_t proto
        , uint32_t type) {
    memset(atapi_cmnd, 0, sizeof(struct lv2_atapi_cmnd_block));
    atapi_cmnd->pktlen = 12;
    atapi_cmnd->blocks = 1;
    atapi_cmnd->block_size = block_size; /* transfer size is block_size * blocks */
    atapi_cmnd->proto = proto;
    atapi_cmnd->in_out = type;
}
static inline int sys_storage_send_atapi_command(uint32_t fd, struct lv2_atapi_cmnd_block *atapi_cmnd, uint8_t *buffer) {
    uint64_t tag;
    system_call_7(SYS_STORAGE_EXECUTE_DEVICE_COMMAND
            , fd
            , LV2_STORAGE_SEND_ATAPI_COMMAND
            , (uint32_t) atapi_cmnd
            , sizeof (struct lv2_atapi_cmnd_block)
            , (uint32_t) buffer
            , atapi_cmnd->block_size
            , (uint32_t) & tag);
    return_to_user_prog(int);
}
int ps3rom_lv2_get_configuration(int fd, uint8_t *buffer) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 0x10, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_GET_CONFIGURATION;
    atapi_cmnd.pkt[1] = 0;
    atapi_cmnd.pkt[2] = 0xff;
    atapi_cmnd.pkt[3] = 0x41;
    atapi_cmnd.pkt[8] = 0x10;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    // if (buffer[10] & 1 == 0) return 0xF000FFFF
    // if (buffer[0] & 1 != 0) exec_mode_sense
    return res;
}
int ps3rom_lv2_mode_sense(int fd, uint8_t *buffer) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 0x10, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_MODE_SENSE_10;
    atapi_cmnd.pkt[1] = 0x08;
    atapi_cmnd.pkt[2] = 0x03;
    atapi_cmnd.pkt[8] = 0x10;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    // if (buffer[11] == 2) exec_mode_select
    return res;
}
int ps3rom_lv2_mode_select(int fd) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    static uint8_t buffer[256];
    memset(buffer, 0, sizeof (buffer));
    buffer[1] = 0x0e;
    buffer[7] = 8;
    buffer[8] = 3;
    buffer[9] = 6;
    buffer[11] = 3; // ? 3 == SACD
    buffer[255] = 0x10;
    init_atapi_cmnd_block(&atapi_cmnd, 0x10, PIO_DATA_OUT_PROTO, DIR_WRITE);
    atapi_cmnd.pkt[0] = GPCMD_MODE_SELECT_10;
    atapi_cmnd.pkt[1] = 0x10; /* PF */
    atapi_cmnd.pkt[8] = 0x10;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_enable_encryption(int fd, uint8_t *buffer, uint32_t lba) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 0x0a, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_READ_DVD_STRUCTURE;
    atapi_cmnd.pkt[1] = 2;
   
atapi_cmnd.pkt[2] = lba >> 24;
atapi_cmnd.pkt[3] = lba >> 16;
atapi_cmnd.pkt[4] = lba >> 8;
atapi_cmnd.pkt[5] = lba & 0xff;
   
    atapi_cmnd.pkt[9] = 0x0a;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_get_event_status_notification(int fd, uint8_t *buffer) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 0x08, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
    atapi_cmnd.pkt[1] = 1; /* IMMED */
    atapi_cmnd.pkt[4] = 4; /* media event */
    atapi_cmnd.pkt[8] = 0x08;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_report_key_start(int fd, uint8_t *buffer) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 0x08, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_REPORT_KEY;
    atapi_cmnd.pkt[2] = 0;
    atapi_cmnd.pkt[3] = 0;
    atapi_cmnd.pkt[4] = 0;
    atapi_cmnd.pkt[5] = 0x08;
    atapi_cmnd.pkt[6] = 0;
    atapi_cmnd.pkt[7] = 0x10;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_send_key(int fd, uint8_t agid, uint32_t key_size, uint8_t *key, uint8_t sequence) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    uint32_t buffer_size;
    uint8_t buffer[256];
    uint8_t buffer_align = 0;
   
    if ((key_size & 3) != 0) {
      buffer_align = ~(key_size & 3) + 4 + 1;
    }
    buffer_size = key_size + 4 + buffer_align;
    init_atapi_cmnd_block(&atapi_cmnd, buffer_size, PIO_DATA_OUT_PROTO, DIR_WRITE);
    atapi_cmnd.pkt[0] = GPCMD_SEND_KEY;
atapi_cmnd.pkt[2] = buffer_size >> 24;
atapi_cmnd.pkt[3] = buffer_size >> 16;
atapi_cmnd.pkt[4] = buffer_size >> 8;
atapi_cmnd.pkt[5] = buffer_size & 0xff;
   
    atapi_cmnd.pkt[6] = sequence;
    atapi_cmnd.pkt[7] = 0x10;
    atapi_cmnd.pkt[10] = agid;
memset(buffer, 0, sizeof(buffer));
buffer[0] = key_size >> 24;
buffer[1] = key_size >> 16;
buffer[2] = key_size >> 8;
buffer[3] = key_size & 0xff;
    memcpy(buffer + 4, key, key_size);
if (buffer_align != 0) {
  memset(buffer + key_size + 4, 0, buffer_align);
  }
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_report_key(int fd, uint8_t agid, uint32_t *key_size, uint8_t *key, uint8_t sequence) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    uint32_t buffer_size;
    uint8_t buffer[256];
    uint8_t buffer_align = 0;
    uint32_t new_key_size, old_key_size = *key_size;
    memset(buffer, 0xff, sizeof(buffer));
   
    if ((old_key_size & 3) != 0) {
      buffer_align = ~(old_key_size & 3) + 4 + 1;
    }
    buffer_size = old_key_size + 4 + buffer_align;
    init_atapi_cmnd_block(&atapi_cmnd, buffer_size, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_REPORT_KEY;
atapi_cmnd.pkt[2] = buffer_size >> 24;
atapi_cmnd.pkt[3] = buffer_size >> 16;
atapi_cmnd.pkt[4] = buffer_size >> 8;
atapi_cmnd.pkt[5] = buffer_size & 0xff;
    atapi_cmnd.pkt[6] = sequence;
    atapi_cmnd.pkt[7] = 0x10;
    atapi_cmnd.pkt[10] = agid;
   
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    new_key_size = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
    *key_size = new_key_size;
    memcpy(key, buffer + 4, (old_key_size > new_key_size ? new_key_size : old_key_size));
    return res;
}
int ps3rom_lv2_report_key_finish(int fd, uint8_t agid) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 0, NON_DATA_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_REPORT_KEY;
    atapi_cmnd.pkt[6] = 0xff;
    atapi_cmnd.pkt[7] = 0x10;
    atapi_cmnd.pkt[10] = agid;
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, 0);
    return res;
}
int ps3rom_lv2_read_toc_header(int fd, uint8_t *buffer) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 12, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_READ_TOC_PMA_ATIP;
    atapi_cmnd.pkt[6] = 0;
    atapi_cmnd.pkt[8] = 12; /* LSB of length */
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_read_toc_entry(int fd, uint8_t *buffer) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 12, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_READ_TOC_PMA_ATIP;
    atapi_cmnd.pkt[6] = 0x01;
    atapi_cmnd.pkt[8] = 12; /* LSB of length */
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
int ps3rom_lv2_read_track(int fd, uint8_t *buffer, uint8_t track) {
    int res;
    struct lv2_atapi_cmnd_block atapi_cmnd;
    init_atapi_cmnd_block(&atapi_cmnd, 48, PIO_DATA_IN_PROTO, DIR_READ);
    atapi_cmnd.pkt[0] = GPCMD_READ_TRACK_RZONE_INFO;
    atapi_cmnd.pkt[1] = 1;
    atapi_cmnd.pkt[5] = track; /* track */
    atapi_cmnd.pkt[8] = 48; /* LSB of length */
    res = sys_storage_send_atapi_command(fd, &atapi_cmnd, buffer);
    return res;
}
</pre>
Please note that all contributions to PS3 Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PS3 Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)