SC Communication: Difference between revisions
Jump to navigation
Jump to search
m (→Syscon Services: 0x20) |
m (→Syscon Packet Headers: Debug header.) |
||
Line 56: | Line 56: | ||
=Syscon Packet Headers= | =Syscon Packet Headers= | ||
* Some useful packet headers... | * Some useful packet headers... | ||
* If the header is shorter than 0x10, you must add your own size. | |||
{| class="wikitable FCK__ShowTableBorders" | {| class="wikitable FCK__ShowTableBorders" | ||
|- | |- | ||
! What? !! Description || Data | ! What? !! Description || Data || Notes | ||
|- | |- | ||
| AUTH1 || AUTH1 Header || 0x1F,0x01,0x00,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30 | | AUTH1 || AUTH1 Header || 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00,<br>0x00, 0x30, 0x00, 0x30 || | ||
|- | |- | ||
| AUTH2 || AUTH2 Header || 0x1F,0x01,0x00,0x01,0x00,0x00,0x80,0x21,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30 | | AUTH2 || AUTH2 Header || 0x1F, 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x21, 0x00, 0x00, 0x00, 0x00,<br>0x00, 0x30, 0x00, 0x30 || | ||
|- | |||
| Debug Output || Sends string to Syscon TTY || 0x20, 0x01, 0x00, 0x07, 0x00, 0x00, 0x80, 0x28, 0x00, 0x00, 0x00, 0x00<br>|| Start message with 0x00. Will print as much as packet length. | |||
|} | |} | ||
Revision as of 02:31, 29 January 2013
Introduction
- The following information was reverse engineered from lv0ldr, lv0, lv1, and sc_iso.self.
- Big thanks to graf_chokolo for a large part of the basis of this page, and to Jestero for Syscon Authentication info!
Overview of Syscon Communication
- Syscon lives at the mmio space of 0x24000080000.
- Communication occurs through mmio read/writes.
List of known offsets in Syscon:
Offset (from start of address space) | Size | Description |
---|---|---|
0xC000 | 0xFF0 | Syscon packet send area |
0xCFF0 | 0x4 | Syscon sent packet counter |
0xCFF4 | 0x4 | Syscon sent packet acknowledge counter |
0xD000 | 0xFF0 | Syscon packet receive area |
0xDFF0 | 0x4 | Syscon received packet counter |
0xDFF4 | 0x4 | Syscon received packet acknowledge counter |
0xE100 | 0x4 | Tells syscon there is a packet to be received |
Quick explanation of the packet counters:
- There are two counters that are incremented by each side (Cell / Syscon).
- 0xCFF0 and 0xDFF0 are incremented by the sending side (Syscon for 0xCFF0, Cell for 0xDFF0)
- 0xCFF4 and 0xDFF4 are incremented by the receiving side (Cell for 0xCFF4, Syscon for 0xDFF4)
Syscon Services
- To be completed...
Service ID | Description |
---|---|
0x14 | NVS Service - Used for eeprom read/write (Non-Volatile Storage?) |
0x18 | Livelock(?) Service - Checks for permission to use other services |
0x20 | Syscon Debug Output(?) - Used to send a string to syscon. |
0x1F | Authenticated Services |
0xFF | Syscon Init (Seen in lv0ldr init sequence to syscon: http://www.ps3devwiki.com/wiki/User_talk:JuanNadie) |
Syscon Packet Headers
- Some useful packet headers...
- If the header is shorter than 0x10, you must add your own size.
What? | Description | Data | Notes |
---|---|---|---|
AUTH1 | AUTH1 Header | 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30 |
|
AUTH2 | AUTH2 Header | 0x1F, 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30 |
|
Debug Output | Sends string to Syscon TTY | 0x20, 0x01, 0x00, 0x07, 0x00, 0x00, 0x80, 0x28, 0x00, 0x00, 0x00, 0x00 |
Start message with 0x00. Will print as much as packet length. |
Syscon Authentication
- An IV of 0x00 is used for most AES steps.
Step 1 - Generate Individual Seeds
Encrypt sc_iso metadata seeds w/ eid root key / iv.
aes256cbc_enc(eid_root_erk, eid_root_riv, sc_module_seeds, 0x40, sc_module_seeds);
Step 2 - Generate SC_ISO encrypted keys
Encrypt the sc_key_seeds.
indiv_key = sc_module_seeds + 0x20; for (int i = 0; i < 0x100; i += 0x10) aes256cbc_enc(indiv_key, zero_iv, key_seeds + i, 0x10, enc_key_seeds + i);
Step 3 - Authenticate with Syscon
Pick a session_id. Must be <= 7.
Step 3a - Secure Packet Header
struct secure_payload_header { u8 session_id; u8 seq_service_id; //service_ID (Unsecure uses 0xFF, AUTH1 = 0x02, AUTH2 = 0x03, READ/WRITE = 0x04) u8 packet_type; //0xFF for BE->SC, 0x00 for SC->BE (if success) u8 magic[0x2]; //0xAD1A u8 prng_random[0xB] //Random shit for padding };
Step 3b - AUTH 1 to SC
uint8_t random_shit[0x10]; auth_key_1_0x01 = enc_key_seeds + (session_id * (0x10*2)); auth_key_2_0x01 = enc_key_seeds + (session_id * (0x10*2) + 0x10); //generating random payload for auth1 rnd_gen(random_shit, 0x10); //create auth1 random data aes128cbc_enc(auth_key_1_0x01, zero_iv, random_shit, 0x10, secure_payload_buf + 0x10); //length = 0x20 //Create secure header/footer // create header: 5 bytes + random stuff (0xb) payload_header->session_id = session_id; payload_header->seq_service_id = seq_service_id++; // starts at 0 payload_header->packet_type = 0xFF; payload_header->magic[0] = 0xAD; payload_header->magic[1] = 0x1A; rnd_gen((u8*) &payload_header->prng_random, 0x0B); //encrypt payload aes128cbc_enc(be2sc_key, zero_iv, secure_payload_buf, length, secure_payload_buf); // create footer: omac1 of the whole packet aesOmac1Mode(secure_payload_buf + length, secure_payload_buf, length, be2sc_key, sizeof(be2sc_key)*8); //Set regular header memcpy(sc_packet, auth1_pkt_header, 0x10); //Send packet. 0x40 Bytes
Step 3c - Validate AUTH1
First, check the header/footer.
- Calulcate aesOmac over the packet length and compare to omac from syscon. Use sc2be key.
- Decrypt internal packet with sc2be key. Use AES128-CBC
- Compare returned session_id and seq_service_id.
- Check secure_payload_buf[0x2] == 0.
Then check the AUTH1 response
// decrypt secure_payload for (i = 0x0; i < 0x20; i += 0x10) aes128cbc(auth_key_2_0x01, zero_iv, secure_payload_buf + 0x10 + i, 0x10, secure_payload_buf + 0x10 + i); // check if challange returned from syscon is correct res = memcmp(secure_payload_buf + 0x10, random_shit, 0x10); if (res != 0) return -1; // save the new challange needed for AUTH2 memcpy(auth_challenge, secure_payload_buf + 0x20, 0x10);
Step 3d - AUTH2 to SC
//AUTH2 Challenge Payload aes128cbc_enc(auth_key_1_0x01, zero_iv, auth_challenge, 0x10, secure_payload_buf + 0x10); //length = 0x20 //Create secure header/footer // create header: 5 bytes + random stuff (0xb) payload_header->session_id = session_id; payload_header->seq_service_id = seq_service_id++; // starts at 0 payload_header->packet_type = 0xFF; payload_header->magic[0] = 0xAD; payload_header->magic[1] = 0x1A; rnd_gen((u8*) &payload_header->prng_random, 0x0B); //encrypt payload aes128cbc_enc(be2sc_key, zero_iv, secure_payload_buf, length, secure_payload_buf); // create footer: omac1 of the whole packet aesOmac1Mode(secure_payload_buf + length, secure_payload_buf, length, be2sc_key, sizeof(be2sc_key)*8); //Set regular header memcpy(sc_packet, auth2_pkt_header, 0x10); //Put packet - 0x40 packet length
Step 3e - Validate AUTH2
Again, check the header/footer.
- Calulcate aesOmac over the packet length and compare to omac from syscon. Use sc2be key.
- Decrypt internal packet with sc2be key. Use AES128-CBC
- Compare returned session_id and seq_service_id.
- Check secure_payload_buf[0x2] == 0.
// encrypt random_shit using auth_challenge (returned from AUTH1 reply) as key and 0 IV aes128cbc_enc(auth_challenge, zero_iv, random_shit, 0x10, session_key); // encrypt result in place with session_key_create[0x10 * sess_id] and IV 0 (result will be the session_key) aes128cbc_enc(session_key_create + (session_id * 0x10), zero_iv, session_key, 0x10, session_key); // use the session_key to decrypt auth2_payload in place (0x10) aes128cbc(session_key, zero_iv, secure_payload_buf + 0x10, 0x10, secure_payload_buf + 0x10); // compare the result with a 0x10 zero string res = memcmp(secure_payload_buf + 0x10, zero_iv, 0x10); //res == 0x0 is good.
Step 4 - Profit?
You are now authenticated with syscon, and can use privileged commands. Just use the session_key calculated from the AUTH2 reply to encrypt/decrypt responses.