Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,9 @@ refs/*
# Local backup files.
*_old

# Build artifacts from lib/.
/lib/*.o
/lib/lib.a
/lib/lib-ps5.a
/lib/lib-elf.a
/lib/lib-elf-ps5.a

/lib/syscalls.asm
/lib/syscalls-ps5.asm

# Build artifacts from prosper0gdb/.
/prosper0gdb/*.o
/prosper0gdb/payload.elf
/prosper0gdb/payload.bin

# Build artifacts from ps5-kstuff-ldr/.
/ps5-kstuff-ldr/kstuff.elf
/ps5-kstuff-ldr/payload_bin.c
Expand All @@ -33,3 +22,9 @@ refs/*
/ps5-kstuff/uelf/uelf.bin
/ps5-kstuff/debug-reader.bin
/ps5-kstuff/debug-reader.elf
/ps5-kstuff/.build-config
logs/
*.bin
*.elf
*.o
*.a
19 changes: 16 additions & 3 deletions ps5-kstuff/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ UELF_ARCH ?= -march=znver2 -mtune=znver2
KSTUFF_OBS ?= 0

ALL_TARGETS := payload.bin
BUILD_CONFIG := .build-config

ifeq ($(KSTUFF_OBS),1)
ifndef PS5_PAYLOAD_SDK
Expand All @@ -16,7 +17,19 @@ endif
all: $(ALL_TARGETS)

clean:
rm -f payload.elf payload.bin debug-reader.elf debug-reader.bin freebsd-loader kelf kelf.o structs.h structs.inc uelf/uelf uelf/uelf.bin uelf/crt.o
rm -f payload.elf payload.bin debug-reader.elf debug-reader.bin freebsd-loader kelf kelf.o structs.h structs.inc uelf/uelf uelf/uelf.bin uelf/crt.o $(BUILD_CONFIG)

.PHONY: FORCE
FORCE:

$(BUILD_CONFIG): FORCE
@tmp="$@.tmp"; \
printf 'KSTUFF_OBS=%s\n' "$(KSTUFF_OBS)" > "$$tmp"; \
printf 'EXTRA_CFLAGS=%s\n' "$(EXTRA_CFLAGS)" >> "$$tmp"; \
printf 'PAYLOAD_OPT=%s\n' "$(PAYLOAD_OPT)" >> "$$tmp"; \
printf 'UELF_OPT=%s\n' "$(UELF_OPT)" >> "$$tmp"; \
printf 'UELF_ARCH=%s\n' "$(UELF_ARCH)" >> "$$tmp"; \
if test -f "$@" && cmp -s "$$tmp" "$@"; then rm -f "$$tmp"; else mv "$$tmp" "$@"; fi

../lib/lib-elf-ps5.a:
cd ../lib; $(MAKE)
Expand All @@ -27,7 +40,7 @@ clean:
structs.inc: structs-ps5.inc
cp structs-ps5.inc structs.inc

payload.elf: ../lib/lib-elf-ps5.a ../prosper0gdb/prosper0gdb.o main.c kelf uelf/uelf.bin
payload.elf: ../lib/lib-elf-ps5.a ../prosper0gdb/prosper0gdb.o main.c kelf uelf/uelf.bin $(BUILD_CONFIG)
gcc $(PAYLOAD_OPT) -isystem ../freebsd-headers -nostdinc -nostdlib -fno-stack-protector -static ../lib/lib-elf-ps5.a ../prosper0gdb/prosper0gdb.o $(EXTRA_CFLAGS) -DKSTUFF_OBS=$(KSTUFF_OBS) main.c -DPS5KEK ../prosper0gdb/dbg.c -Wl,-gc-sections -o payload.elf -fPIE -ffreestanding -no-pie -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384

payloa%.bin: payloa%.elf
Expand All @@ -46,7 +59,7 @@ structs.h: structs.inc
uelf/crt.o: uelf/crt.asm
yasm uelf/crt.asm -f elf64 -o uelf/crt.o

uelf/uelf: uelf/*.c uelf/*.h structs.h uelf/crt.o BearSSL/build/libbearssl.a isa-l_crypto/bin/isa-l_crypto.a
uelf/uelf: uelf/*.c uelf/*.h structs.h uelf/crt.o BearSSL/build/libbearssl.a isa-l_crypto/bin/isa-l_crypto.a $(BUILD_CONFIG)
gcc -Wl,-Bsymbolic -Wl,-gc-sections -ffunction-sections -fdata-sections $(UELF_OPT) $(UELF_ARCH) -g -isystem ../freebsd-headers -isystem isa-l_crypto/include -nostdinc -nostdlib -mgeneral-regs-only -fno-stack-protector -fPIE -fPIC -shared -fvisibility=hidden -ffreestanding uelf/crt.o $(EXTRA_CFLAGS) -DKSTUFF_OBS=$(KSTUFF_OBS) uelf/*.c BearSSL/build/libbearssl.a isa-l_crypto/bin/isa-l_crypto.a -o uelf/uelf -Wl,-z,max-page-size=4096

uelf/uelf.bin: uelf/uelf
Expand Down
4 changes: 0 additions & 4 deletions ps5-kstuff/debug-reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ static void print_metrics(const struct kstuff_metrics* metrics)
PRINT_FIELD("emu", metrics->crypto_requests_emulated);
PRINT_FIELD("fallback", metrics->crypto_requests_fallback);
PRINT_FIELD("fail", metrics->crypto_requests_failed);
PRINT_FIELD("restart", metrics->crypto_requests_restarted);
PRINT_FIELD("msg", metrics->crypto_messages_total);
PRINT_FIELD("xts_msg", metrics->crypto_messages_xts);
PRINT_FIELD("hmac_msg", metrics->crypto_messages_hmac);
Expand All @@ -259,8 +258,6 @@ static void print_metrics(const struct kstuff_metrics* metrics)
PRINT_FIELD("req", metrics->xts_requests);
PRINT_FIELD("sectors", metrics->xts_sectors);
PRINT_FIELD("run_msg", metrics->xts_run_messages_total);
PRINT_FIELD("coalesced", metrics->xts_run_coalesced_messages);
PRINT_FIELD("skipped", metrics->xts_run_skip_sectors);
PRINT_FIELD("direct_runs", metrics->xts_full_direct_runs);
PRINT_FIELD("direct_sectors", metrics->xts_full_direct_sectors);
PRINT_FIELD("fallback", metrics->xts_full_fallback_sectors);
Expand Down Expand Up @@ -291,7 +288,6 @@ static void print_metrics(const struct kstuff_metrics* metrics)
PRINT_FIELD("hmac_shape", metrics->fpkg_reject_hmac_bad_shape);
PRINT_FIELD("other", metrics->fpkg_reject_other_message);
PRINT_FIELD("no_emu", metrics->fpkg_request_no_emulation);
PRINT_FIELD("partial", metrics->fpkg_request_partial_emulation);
PRINT_FIELD("fpu_fail", metrics->fpkg_request_fpu_enter_fail);
tee_putc('\n');

Expand Down
108 changes: 19 additions & 89 deletions ps5-kstuff/uelf/fpkg.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ static struct crypto_message_info inspect_crypto_message(const uint64_t msg_data
}

static struct crypto_message_result handle_hmac_message(uint64_t msg, const uint64_t msg_data[21],
int key_idx, uint64_t bytes_cap,
uint64_t* bytes_handled,
int key_idx,
struct crypto_request_cache* cache)
{
struct crypto_message_result result = unhandled_crypto_message(msg);
Expand All @@ -138,8 +137,7 @@ static struct crypto_message_result handle_hmac_message(uint64_t msg, const uint
return result;

uint8_t hash[32] = {0};
*bytes_handled += msg_data[1];
if(bytes_cap < *bytes_handled && pfs_hmac_virtual_fpu_held(cache, hash, key_idx, key, msg_data[2], msg_data[1]))
if(pfs_hmac_virtual_fpu_held(cache, hash, key_idx, key, msg_data[2], msg_data[1]))
{
result.emulated_messages = 1;
result.status = -1;
Expand All @@ -156,71 +154,30 @@ static struct crypto_message_result handle_hmac_message(uint64_t msg, const uint
return result;
}

static struct crypto_message_result handle_xts_message_run(uint64_t msg, const uint64_t first_msg_data[21],
int key_idx,
uint64_t bytes_cap, uint64_t* bytes_handled,
struct crypto_request_cache* cache)
static struct crypto_message_result handle_xts_message(uint64_t msg, const uint64_t msg_data[21],
int key_idx,
struct crypto_request_cache* cache)
{
struct crypto_message_result result = unhandled_crypto_message(msg);
uint8_t key[32];
if(!get_fake_key(key_idx, key))
return result;
METRIC_INC(xts_run_messages_total);

uint64_t src = first_msg_data[2];
uint64_t dst = first_msg_data[3];
uint64_t start_sector = first_msg_data[4];
uint32_t total_sectors = (uint32_t)first_msg_data[1];
int is_encrypt = (first_msg_data[0] & 0x800) >> 11;
uint64_t cursor = msg;
uint64_t src = msg_data[2];
uint64_t dst = msg_data[3];
uint64_t start_sector = msg_data[4];
uint32_t total_sectors = (uint32_t)msg_data[1];
int is_encrypt = (msg_data[0] & 0x800) >> 11;

while(result.next_msg)
if(pfs_xts_virtual_fpu_held(cache, dst, src, key_idx, key, start_sector, total_sectors, is_encrypt))
{
uint64_t next_msg_data[21];
if(read_crypto_message(result.next_msg, next_msg_data))
break;
if(!is_xts_message(next_msg_data))
break;
uint32_t next_sectors = (uint32_t)next_msg_data[1];
if(HANDLE_TO_IDX(next_msg_data[5]) != key_idx
|| (int)((next_msg_data[0] & 0x800) >> 11) != is_encrypt
|| next_msg_data[2] != src + ((uint64_t)total_sectors << 12)
|| next_msg_data[3] != dst + ((uint64_t)total_sectors << 12)
|| next_msg_data[4] != start_sector + total_sectors
|| total_sectors > UINT32_MAX - next_sectors)
break;

total_sectors += next_sectors;
cursor = result.next_msg;
result.next_msg = kpeek64(cursor + 320);
result.total_messages++;
}

uint64_t run_bytes = (uint64_t)total_sectors << 12;
uint64_t skip_bytes = 0;
if(bytes_cap > *bytes_handled)
skip_bytes = bytes_cap - *bytes_handled;
if(skip_bytes >= run_bytes)
skip_bytes = run_bytes;
uint32_t skip_sectors = (uint32_t)(skip_bytes >> 12);
*bytes_handled += run_bytes;
METRIC_ADD(xts_run_skip_sectors, skip_sectors);

if(skip_sectors < total_sectors)
{
if(pfs_xts_virtual_fpu_held(cache, dst + ((uint64_t)skip_sectors << 12),
src + ((uint64_t)skip_sectors << 12), key_idx, key,
start_sector + skip_sectors, total_sectors - skip_sectors, is_encrypt))
{
result.emulated_messages = result.total_messages;
result.status = -1;
return result;
}
result.emulated_messages = 1;
result.status = -1;
return result;
}

result.emulated_messages = result.total_messages;
if(result.total_messages > 1)
METRIC_ADD(xts_run_coalesced_messages, result.total_messages - 1);
result.emulated_messages = 1;
result.status = 0;
return result;
}
Expand All @@ -234,7 +191,7 @@ static inline uint64_t rdtsc(void)
}
*/

static int handle_crypto_request(uint64_t* regs, uint64_t bytes_handled)
static int handle_crypto_request(uint64_t* regs)
{
METRIC_TIME_START(start_cycles);
// uint64_t start_time = rdtsc();
Expand All @@ -243,7 +200,6 @@ static int handle_crypto_request(uint64_t* regs, uint64_t bytes_handled)
int total_status = 0;
int handled = 0;
int fpu_entered = 0;
uint64_t new_bytes_handled = 0;
METRIC_INC(crypto_requests_total);

uint64_t start = (FWVER >= 0x800) ? regs[RBX] : regs[R14];
Expand Down Expand Up @@ -277,30 +233,13 @@ static int handle_crypto_request(uint64_t* regs, uint64_t bytes_handled)

struct crypto_message_result result;
if(msg_info.kind == CRYPTO_MESSAGE_XTS)
result = handle_xts_message_run(msg, msg_data, msg_info.key_idx, bytes_handled, &new_bytes_handled, &s_crypto_request_cache);
result = handle_xts_message(msg, msg_data, msg_info.key_idx, &s_crypto_request_cache);
else if(msg_info.kind == CRYPTO_MESSAGE_HMAC)
result = handle_hmac_message(msg, msg_data, msg_info.key_idx, bytes_handled, &new_bytes_handled, &s_crypto_request_cache);
result = handle_hmac_message(msg, msg_data, msg_info.key_idx, &s_crypto_request_cache);
else
result = unhandled_crypto_message(msg);
int status = result.status;

if (status == EINTR) // partial decrypt, need to restart the syscall
{
METRIC_INC(crypto_requests_restarted);
uint64_t frame[6] = {
MKTRAP(TRAP_FPKG, 2), 0, 0, 0, 0,
new_bytes_handled,
};
if(push_stack_checked(regs, frame, sizeof(frame)))
{
total_status = -1;
break;
}
regs[RIP] = (uint64_t)doreti_iret;
handled = 1;
goto exit;
}

total += result.total_messages;

if (status != ENOSYS)
Expand All @@ -319,7 +258,6 @@ static int handle_crypto_request(uint64_t* regs, uint64_t bytes_handled)
{
// not all requests successfully emulated
// we can't run only part of the request, so just report failure
METRIC_INC(fpkg_request_partial_emulation);
total_status = -1;
}

Expand Down Expand Up @@ -350,7 +288,7 @@ int try_handle_fpkg_trap(uint64_t* regs)
{
if(regs[RIP] == (uint64_t)sceSblServiceCryptAsync_deref_singleton)
{
if(handle_crypto_request(regs, 0))
if(handle_crypto_request(regs))
observe_current_syscall_emulated();
else
{
Expand Down Expand Up @@ -469,14 +407,6 @@ void handle_fpkg_trap(uint64_t* regs, uint32_t trapno)
regs[RIP] = frame[11];
regs[RAX] = 0;
}
else if(trapno == 2)
{
uint64_t frame[6];
if(pop_stack_checked(regs, frame, sizeof(frame)))
return;
regs[RIP] = (uint64_t)sceSblServiceCryptAsync_deref_singleton;
handle_crypto_request(regs, frame[5]);
}
}

static const uint64_t dbgregs_for_nmount[6] = {
Expand Down
Loading
Loading