libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
ps3_crypto.c
Go to the documentation of this file.
1/*
2 * This file is part of the Aaru Data Preservation Suite.
3 * Copyright (c) 2019-2026 Natalia Portillo.
4 *
5 * This library is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; version 2.1 of the License.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see
16 * <https://www.gnu.org/licenses/>.
17 *
18 * PS3 disc encryption: key derivation, sector encrypt/decrypt, IV derivation.
19 */
20
21#include <stdint.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <aaruformat.h>
26
27#include "../lib/aes128.h"
28#include "ps3_crypto.h"
29#include "ps3_encryption_map.h"
30
31/* PS3 Encryption Round Key — publicly known constant */
32static const uint8_t PS3_ERK[16] = {0x38, 0x0B, 0xCF, 0x0B, 0x53, 0x45, 0x5B, 0x3C,
33 0x78, 0x17, 0xAB, 0x4F, 0xA3, 0xBA, 0x90, 0xED};
34
35/* PS3 ERK IV — publicly known constant */
36static const uint8_t PS3_ERK_IV[16] = {0x69, 0x47, 0x47, 0x72, 0xAF, 0x6F, 0xDA, 0xB3,
37 0x42, 0x74, 0x3A, 0xEF, 0xAA, 0x18, 0x62, 0x87};
38
39void ps3_derive_disc_key(const uint8_t data1[16], uint8_t disc_key[16])
40{
41 memcpy(disc_key, data1, 16);
43}
44
45void ps3_derive_iv(uint64_t sector_num, uint8_t iv[16])
46{
47 memset(iv, 0, 16);
48
49 for(int i = 15; i >= 0 && sector_num > 0; i--)
50 {
51 iv[i] = (uint8_t)(sector_num & 0xFF);
52 sector_num >>= 8;
53 }
54}
55
56void ps3_encrypt_sector(const uint8_t disc_key[16], uint64_t sector_num, uint8_t *data, uint32_t length)
57{
58 uint8_t iv[16];
59 ps3_derive_iv(sector_num, iv);
60 aes128_cbc_encrypt(disc_key, iv, data, length);
61}
62
63void ps3_decrypt_sector(const uint8_t disc_key[16], uint64_t sector_num, uint8_t *data, uint32_t length)
64{
65 uint8_t iv[16];
66 ps3_derive_iv(sector_num, iv);
67 aes128_cbc_decrypt(disc_key, iv, data, length);
68}
69
71{
72 if(ctx == NULL) return;
73
74 /* Read disc key from media tags */
75 if(ctx->ps3_disc_key == NULL)
76 {
77 mediaTagEntry *item = NULL;
78 int32_t tag = kMediaTagPs3DiscKey;
79 HASH_FIND_INT(ctx->mediaTags, &tag, item);
80
81 if(item != NULL && item->length == 16)
82 {
83 ctx->ps3_disc_key = (uint8_t *)malloc(16);
84
85 if(ctx->ps3_disc_key != NULL) memcpy(ctx->ps3_disc_key, item->data, 16);
86 }
87 else
88 {
89 /* Try deriving from data1 */
91 HASH_FIND_INT(ctx->mediaTags, &tag, item);
92
93 if(item != NULL && item->length == 16)
94 {
95 ctx->ps3_disc_key = (uint8_t *)malloc(16);
96
97 if(ctx->ps3_disc_key != NULL) ps3_derive_disc_key(item->data, ctx->ps3_disc_key);
98 }
99 }
100 }
101
102 /* Read and deserialize encryption map from media tags */
103 if(ctx->ps3_plaintext_regions == NULL)
104 {
105 mediaTagEntry *item = NULL;
106 int32_t tag = kMediaTagPs3EncryptionMap;
107 HASH_FIND_INT(ctx->mediaTags, &tag, item);
108
109 if(item != NULL && item->length >= 4)
110 {
111 Ps3PlaintextRegion *regions = NULL;
112 uint32_t count = 0;
113
114 if(ps3_deserialize_encryption_map(item->data, item->length, &regions, &count) == 0)
115 {
116 ctx->ps3_plaintext_regions = regions;
117 ctx->ps3_plaintext_region_count = count;
118 }
119 }
120 }
121}
void aes128_cbc_decrypt(const uint8_t key[16], const uint8_t iv[16], uint8_t *data, uint32_t length)
AES-128 CBC decrypt data in-place.
Definition aes128.c:290
void aes128_cbc_encrypt(const uint8_t key[16], const uint8_t iv[16], uint8_t *data, uint32_t length)
AES-128 CBC encrypt data in-place.
Definition aes128.c:274
@ kMediaTagPs3DiscKey
PS3 derived disc key (16 bytes).
Definition aaru.h:1080
@ kMediaTagPs3EncryptionMap
PS3 encryption region map (serialized from sector 0).
Definition aaru.h:1084
@ kMediaTagPs3Data1
PS3 data1 key (16 bytes, from disc).
Definition aaru.h:1081
static const uint8_t PS3_ERK_IV[16]
Definition ps3_crypto.c:36
void ps3_lazy_init(aaruformat_context *ctx)
Lazy-initialize PS3 encryption state from context media tags.
Definition ps3_crypto.c:70
void ps3_derive_disc_key(const uint8_t data1[16], uint8_t disc_key[16])
Derive a PS3 disc key from a data1 key.
Definition ps3_crypto.c:39
void ps3_derive_iv(uint64_t sector_num, uint8_t iv[16])
Derive the per-sector AES IV from a sector number.
Definition ps3_crypto.c:45
static const uint8_t PS3_ERK[16]
Definition ps3_crypto.c:32
void ps3_decrypt_sector(const uint8_t disc_key[16], uint64_t sector_num, uint8_t *data, uint32_t length)
Decrypt a sector using PS3 disc encryption (AES-128-CBC).
Definition ps3_crypto.c:63
void ps3_encrypt_sector(const uint8_t disc_key[16], uint64_t sector_num, uint8_t *data, uint32_t length)
Encrypt a sector using PS3 disc encryption (AES-128-CBC).
Definition ps3_crypto.c:56
int32_t ps3_deserialize_encryption_map(const uint8_t *data, uint32_t length, Ps3PlaintextRegion **regions, uint32_t *count)
Deserialize plaintext regions from little-endian binary (media tag format).
A plaintext (unencrypted) region on a PS3 disc.
Master context representing an open or in‑creation Aaru image.
Definition context.h:175
uint8_t * ps3_disc_key
Cached disc key (16 bytes), NULL if not loaded.
Definition context.h:348
uint32_t ps3_plaintext_region_count
Number of plaintext regions.
Definition context.h:350
mediaTagEntry * mediaTags
Hash table of extra media tags (uthash root).
Definition context.h:267
void * ps3_plaintext_regions
Parsed Ps3PlaintextRegion array (max 32), NULL if not loaded.
Definition context.h:349
Hash table entry for an arbitrary media tag (e.g., proprietary drive/medium descriptor).
Definition context.h:122
uint8_t * data
Tag data blob (opaque to library core); length bytes long.
Definition context.h:123
uint32_t length
Length in bytes of data.
Definition context.h:125