Skip to content

Commit 00abf29

Browse files
committed
fix(sep): add some locking for aess
1 parent e3536a3 commit 00abf29

File tree

2 files changed

+78
-46
lines changed
  • hw/arm/apple-silicon
  • include/hw/arm/apple-silicon

2 files changed

+78
-46
lines changed

hw/arm/apple-silicon/sep.c

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,12 +2042,13 @@ static void aess_raise_interrupt(AppleAESSState *s)
20422042
// For the PKA ECDH command, reuse code from SSC.
20432043

20442044
static void aess_keywrap_uid(AppleAESSState *s, uint8_t *in, uint8_t *out,
2045-
QCryptoCipherAlgo cipher_alg)
2045+
QCryptoCipherAlgo cipher_alg, uint32_t cmd,
2046+
uint32_t reg_0x18_keydisable)
20462047
{ // for keywrap only
20472048
// TODO: Second half of output might be CMAC!!!
20482049
g_assert_cmpuint(cipher_alg, ==, QCRYPTO_CIPHER_ALGO_AES_256);
20492050
QCryptoCipher *cipher;
2050-
uint32_t normalized_cmd = SEP_AESS_CMD_WITHOUT_FLAGS(s->command);
2051+
uint32_t normalized_cmd = SEP_AESS_CMD_WITHOUT_FLAGS(cmd);
20512052
size_t key_len = qcrypto_cipher_get_key_len(cipher_alg);
20522053
size_t data_len = 0x20;
20532054
g_assert_cmpuint(data_len, ==, 0x20);
@@ -2068,12 +2069,12 @@ static void aess_keywrap_uid(AppleAESSState *s, uint8_t *in, uint8_t *out,
20682069
// in the same output keys.
20692070
xor_32bit_value(&used_key[0x10], s->reg_0x14_keywrap_iterations_counter,
20702071
0x8 / 4); // seed_bits are only for keywrap
2071-
DPRINTF("%s: s->command: 0x%02x normalized_cmd: 0x%02x cipher_alg: %u; "
2072+
DPRINTF("%s: cmd: 0x%02x normalized_cmd: 0x%02x cipher_alg: %u; "
20722073
"key_len: %lu; iterations: %u, seed_bits: 0x%02x, "
20732074
"reg_0x18_keydisable: 0x%02x\n",
2074-
__func__, s->command, normalized_cmd, cipher_alg, key_len,
2075+
__func__, cmd, normalized_cmd, cipher_alg, key_len,
20752076
s->reg_0x14_keywrap_iterations_counter, s->seed_bits,
2076-
s->reg_0x18_keydisable);
2077+
reg_0x18_keydisable);
20772078
HEXDUMP("aess_keywrap_uid: used_key", used_key, sizeof(used_key));
20782079
HEXDUMP("aess_keywrap_uid: in", in, data_len);
20792080
cipher = qcrypto_cipher_new(cipher_alg, QCRYPTO_CIPHER_MODE_CBC, used_key,
@@ -2127,17 +2128,14 @@ static int aess_get_custom_keywrap_index(uint32_t cmd)
21272128
}
21282129
}
21292130

2130-
static bool check_register_0x18_KEYDISABLE_BIT_INVALID(AppleAESSState *s)
2131+
static bool check_register_0x18_KEYDISABLE_BIT_INVALID(uint32_t cmd, uint32_t reg_0x18_keydisable)
21312132
{
2132-
////uint32_t normalized_cmd = SEP_AESS_CMD_WITHOUT_FLAGS(s->command);
2133-
////uint32_t cmd = s->command;
2134-
uint32_t cmd = SEP_AESS_CMD_WITHOUT_KEYSIZE(s->command);
2135-
bool reg_0x18_keydisable_bit0 = (s->reg_0x18_keydisable & 0x1) != 0;
2136-
bool reg_0x18_keydisable_bit1 = (s->reg_0x18_keydisable & 0x2) != 0;
2137-
bool reg_0x18_keydisable_bit3 = (s->reg_0x18_keydisable & 0x8) != 0;
2138-
bool reg_0x18_keydisable_bit4 = (s->reg_0x18_keydisable & 0x10) != 0;
2139-
////switch (normalized_cmd)
2140-
switch (cmd) {
2133+
uint32_t cmd_without_keysize = SEP_AESS_CMD_WITHOUT_KEYSIZE(cmd);
2134+
bool reg_0x18_keydisable_bit0 = (reg_0x18_keydisable & 0x1) != 0;
2135+
bool reg_0x18_keydisable_bit1 = (reg_0x18_keydisable & 0x2) != 0;
2136+
bool reg_0x18_keydisable_bit3 = (reg_0x18_keydisable & 0x8) != 0;
2137+
bool reg_0x18_keydisable_bit4 = (reg_0x18_keydisable & 0x10) != 0;
2138+
switch (cmd_without_keysize) {
21412139
// case 0x: // driver_op == 0x09 (cmd 0x00, invalid)
21422140
case 0x0C:
21432141
case 0x4C:
@@ -2174,17 +2172,25 @@ static bool check_register_0x18_KEYDISABLE_BIT_INVALID(AppleAESSState *s)
21742172

21752173
static void aess_handle_cmd(AppleAESSState *s)
21762174
{
2175+
uint32_t cmd, reg_0x18_keydisable;
2176+
// comment this and the second one below out when not using async
2177+
// if using QEMU_LOCK_GUARD (non-WITH_) in write
2178+
WITH_QEMU_LOCK_GUARD(&s->lock) {
2179+
cmd = s->command;
2180+
reg_0x18_keydisable = s->reg_0x18_keydisable;
2181+
}
2182+
21772183
bool keyselect_non_gid0 =
2178-
SEP_AESS_CMD_FLAG_KEYSELECT_GID1_CUSTOM(s->command) != 0;
2179-
bool keyselect_gid1 = (s->command & SEP_AESS_CMD_FLAG_KEYSELECT_GID1) != 0;
2184+
SEP_AESS_CMD_FLAG_KEYSELECT_GID1_CUSTOM(cmd) != 0;
2185+
bool keyselect_gid1 = (cmd & SEP_AESS_CMD_FLAG_KEYSELECT_GID1) != 0;
21802186
bool keyselect_custom =
2181-
(s->command & SEP_AESS_CMD_FLAG_KEYSELECT_CUSTOM) != 0;
2182-
uint32_t normalized_cmd = SEP_AESS_CMD_WITHOUT_FLAGS(s->command);
2183-
QCryptoCipherAlgo cipher_alg = get_aes_cipher_alg(s->command);
2187+
(cmd & SEP_AESS_CMD_FLAG_KEYSELECT_CUSTOM) != 0;
2188+
uint32_t normalized_cmd = SEP_AESS_CMD_WITHOUT_FLAGS(cmd);
2189+
QCryptoCipherAlgo cipher_alg = get_aes_cipher_alg(cmd);
21842190
size_t key_len = qcrypto_cipher_get_key_len(cipher_alg);
21852191
bool zero_iv_two_blocks_encryption = false;
21862192
bool register_0x18_KEYDISABLE_BIT_INVALID =
2187-
check_register_0x18_KEYDISABLE_BIT_INVALID(s);
2193+
check_register_0x18_KEYDISABLE_BIT_INVALID(cmd, reg_0x18_keydisable);
21882194
bool valid_command = true;
21892195
bool invalid_parameters = register_0x18_KEYDISABLE_BIT_INVALID;
21902196
#if 1
@@ -2220,7 +2226,8 @@ static void aess_handle_cmd(AppleAESSState *s)
22202226
/// false);
22212227
// aess_keywrap_uid(s, key_wrap_data_in, key_wrap_data_out, cipher_alg,
22222228
// true);
2223-
aess_keywrap_uid(s, key_wrap_data_in, key_wrap_data_out, cipher_alg);
2229+
aess_keywrap_uid(s, key_wrap_data_in, key_wrap_data_out, cipher_alg,
2230+
cmd, reg_0x18_keydisable);
22242231
// qemu_guest_getrandom_nofail(key_wrap_data_out, sizeof(
22252232
// key_wrap_data_out)); // For testing if random output breaks stuff.
22262233
memcpy(s->out_full, key_wrap_data_out, key_len);
@@ -2235,7 +2242,7 @@ static void aess_handle_cmd(AppleAESSState *s)
22352242
SEP_AESS_COMMAND_ENCRYPT_CBC_ONLY_NONCUSTOM_FORCE_CUSTOM_AES256) /* GID0 || GID1 || Custom */
22362243
{
22372244
bool custom_encryption = false;
2238-
DPRINTF("%s: s->command 0x%03x ; ", __func__, s->command);
2245+
DPRINTF("%s: cmd 0x%03x ; ", __func__, cmd);
22392246
HEXDUMP("s->in_full", s->in_full, sizeof(s->in_full));
22402247
if (normalized_cmd ==
22412248
SEP_AESS_COMMAND_ENCRYPT_CBC_ONLY_NONCUSTOM_FORCE_CUSTOM_AES256) {
@@ -2261,7 +2268,7 @@ static void aess_handle_cmd(AppleAESSState *s)
22612268
uint8_t used_key[0x20] = { 0 };
22622269
if (custom_encryption) {
22632270
int custom_keywrap_index =
2264-
aess_get_custom_keywrap_index(s->command & 0xFF);
2271+
aess_get_custom_keywrap_index(cmd & 0xFF);
22652272
if (s->custom_key_index_enabled[custom_keywrap_index]) {
22662273
memcpy(used_key, s->custom_key_index[custom_keywrap_index],
22672274
sizeof(used_key));
@@ -2304,7 +2311,7 @@ static void aess_handle_cmd(AppleAESSState *s)
23042311
&error_abort); // sizeof(iv) == 0x10 on 256 and 128
23052312
qcrypto_cipher_encrypt(cipher, s->in_full, s->out_full,
23062313
sizeof(s->in_full), &error_abort);
2307-
// if ((s->command & 0xF) == 0x9)
2314+
// if ((cmd & 0xF) == 0x9)
23082315
} else if (do_encryption) {
23092316
qcrypto_cipher_setiv(
23102317
cipher, iv, sizeof(iv),
@@ -2373,16 +2380,16 @@ static void aess_handle_cmd(AppleAESSState *s)
23732380
// 0x248/0x2C8(0x2C1)
23742381
else if (normalized_cmd == 0x1) {
23752382
int custom_keywrap_index =
2376-
aess_get_custom_keywrap_index(s->command & 0xFF);
2383+
aess_get_custom_keywrap_index(cmd & 0xFF);
23772384
memcpy(s->custom_key_index[custom_keywrap_index], s->in_full,
23782385
sizeof(s->custom_key_index[custom_keywrap_index]));
23792386
// unset (real zero-key) != zero-key set (not real zero-key)
23802387
xor_32bit_value(s->custom_key_index[custom_keywrap_index], 0xDEADBEEF,
23812388
0x20 / 4);
23822389
s->custom_key_index_enabled[custom_keywrap_index] = true;
23832390
DPRINTF("SEP AESS_BASE: %s: sync/set key command 0x%02x "
2384-
"s->command 0x%02x\n",
2385-
__func__, normalized_cmd, s->command);
2391+
"cmd 0x%02x\n",
2392+
__func__, normalized_cmd, cmd);
23862393
}
23872394
#endif
23882395
// TODO: other sync commands: 0x205(0x201), 0x204(0x281), 0x245(0x241),
@@ -2394,20 +2401,24 @@ static void aess_handle_cmd(AppleAESSState *s)
23942401
#endif
23952402
else {
23962403
DPRINTF("SEP AESS_BASE: %s: Unknown command 0x%02x\n", __func__,
2397-
s->command);
2404+
cmd);
23982405
// valid_command = false;
23992406
}
24002407

24012408
jump_return:
2402-
invalid_parameters |= !valid_command;
2403-
if (invalid_parameters) {
2404-
// always keep this flag
2405-
s->interrupt_status |= SEP_AESS_REGISTER_INTERRUPT_STATUS_UNRECOVERABLE_ERROR_INTERRUPT;
2409+
// comment this and the first one above out when not using async
2410+
// if using QEMU_LOCK_GUARD (non-WITH_) in write
2411+
WITH_QEMU_LOCK_GUARD(&s->lock) {
2412+
invalid_parameters |= !valid_command;
2413+
if (invalid_parameters) {
2414+
// always keep this flag
2415+
s->interrupt_status |= SEP_AESS_REGISTER_INTERRUPT_STATUS_UNRECOVERABLE_ERROR_INTERRUPT;
2416+
}
2417+
s->status &= ~SEP_AESS_REGISTER_STATUS_ACTIVE;
2418+
// call raise_interrupt always instead of only on keywrap, because it's
2419+
// checking conditions
2420+
aess_raise_interrupt(s);
24062421
}
2407-
s->status &= ~SEP_AESS_REGISTER_STATUS_ACTIVE;
2408-
// call raise_interrupt always instead of only on keywrap, because it's
2409-
// checking conditions
2410-
aess_raise_interrupt(s);
24112422
}
24122423

24132424
static void aess_handle_cmd_bh(void *opaque) {
@@ -2422,17 +2433,21 @@ static void aess_base_reg_write(void *opaque, hwaddr addr, uint64_t data,
24222433
AppleSEPState *sep = s->sep;
24232434
uint64_t orig_data = data;
24242435

2436+
//QEMU_LOCK_GUARD(&s->lock);
2437+
24252438
#ifdef ENABLE_CPU_DUMP_STATE
24262439
DPRINTF("\n");
24272440
cpu_dump_state(CPU(sep->cpu), stderr, CPU_DUMP_CODE);
24282441
#endif
24292442
switch (addr) {
24302443
case SEP_AESS_REGISTER_STATUS: // Status
2431-
s->status = data; // surely no bitwise OR?
2432-
if ((s->status & SEP_AESS_REGISTER_STATUS_RUN_COMMAND) != 0) {
2433-
s->status &= ~SEP_AESS_REGISTER_STATUS_RUN_COMMAND;
2434-
s->status |= SEP_AESS_REGISTER_STATUS_ACTIVE;
2435-
s->interrupt_status &= ~SEP_AESS_REGISTER_INTERRUPT_STATUS_DONE;
2444+
if ((data & SEP_AESS_REGISTER_STATUS_RUN_COMMAND) != 0) {
2445+
data &= ~SEP_AESS_REGISTER_STATUS_RUN_COMMAND;
2446+
data |= SEP_AESS_REGISTER_STATUS_ACTIVE;
2447+
WITH_QEMU_LOCK_GUARD(&s->lock) {
2448+
s->status = data; // surely no bitwise OR?
2449+
s->interrupt_status &= ~SEP_AESS_REGISTER_INTERRUPT_STATUS_DONE;
2450+
}
24362451
//aess_handle_cmd(s);
24372452
qemu_bh_schedule(s->command_bh);
24382453
}
@@ -2442,8 +2457,10 @@ static void aess_base_reg_write(void *opaque, hwaddr addr, uint64_t data,
24422457
s->command = data;
24432458
goto jump_log;
24442459
case SEP_AESS_REGISTER_INTERRUPT_STATUS: // Interrupt Status
2445-
if ((data & SEP_AESS_REGISTER_INTERRUPT_STATUS_DONE) != 0) {
2446-
s->interrupt_status &= ~SEP_AESS_REGISTER_INTERRUPT_STATUS_DONE;
2460+
WITH_QEMU_LOCK_GUARD(&s->lock) {
2461+
if ((data & SEP_AESS_REGISTER_INTERRUPT_STATUS_DONE) != 0) {
2462+
s->interrupt_status &= ~SEP_AESS_REGISTER_INTERRUPT_STATUS_DONE;
2463+
}
24472464
}
24482465
goto jump_log;
24492466
case SEP_AESS_REGISTER_INTERRUPT_ENABLED: // Interrupt Enabled
@@ -2503,19 +2520,25 @@ static uint64_t aess_base_reg_read(void *opaque, hwaddr addr, unsigned size)
25032520
AppleSEPState *sep = s->sep;
25042521
uint64_t ret = 0;
25052522

2523+
//QEMU_LOCK_GUARD(&s->lock);
2524+
25062525
#ifdef ENABLE_CPU_DUMP_STATE
25072526
DPRINTF("\n");
25082527
cpu_dump_state(CPU(sep->cpu), stderr, CPU_DUMP_CODE);
25092528
#endif
25102529
switch (addr) {
25112530
case SEP_AESS_REGISTER_STATUS: // Status
2512-
ret = s->status;
2531+
WITH_QEMU_LOCK_GUARD(&s->lock) {
2532+
ret = s->status;
2533+
}
25132534
goto jump_log;
25142535
case SEP_AESS_REGISTER_COMMAND: // Command
25152536
ret = s->command;
25162537
goto jump_log;
25172538
case SEP_AESS_REGISTER_INTERRUPT_STATUS: // Interrupt Status
2518-
ret = s->interrupt_status;
2539+
WITH_QEMU_LOCK_GUARD(&s->lock) {
2540+
ret = s->interrupt_status;
2541+
}
25192542
goto jump_log;
25202543
case SEP_AESS_REGISTER_INTERRUPT_ENABLED: // Interrupt Enabled
25212544
ret = s->interrupt_enabled;
@@ -2717,6 +2740,8 @@ static void pka_base_reg_write(void *opaque, hwaddr addr, uint64_t data,
27172740
ApplePKAState *s = opaque;
27182741
AppleSEPState *sep = s->sep;
27192742

2743+
QEMU_LOCK_GUARD(&s->lock);
2744+
27202745
#ifdef ENABLE_CPU_DUMP_STATE
27212746
cpu_dump_state(CPU(sep->cpu), stderr, CPU_DUMP_CODE);
27222747
#endif
@@ -2787,6 +2812,8 @@ static uint64_t pka_base_reg_read(void *opaque, hwaddr addr, unsigned size)
27872812
AppleSEPState *sep = s->sep;
27882813
uint64_t ret = 0;
27892814

2815+
QEMU_LOCK_GUARD(&s->lock);
2816+
27902817
#ifdef ENABLE_CPU_DUMP_STATE
27912818
cpu_dump_state(CPU(sep->cpu), stderr, CPU_DUMP_CODE);
27922819
#endif
@@ -3577,6 +3604,9 @@ AppleSEPState *apple_sep_from_node(AppleDTNode *node, MemoryRegion *ool_mr,
35773604
address_space_init(s->ool_as, s->ool_mr, "sep.ool");
35783605
#endif
35793606

3607+
qemu_mutex_init(&s->aess_state.lock);
3608+
qemu_mutex_init(&s->pka_state.lock);
3609+
35803610
// No async necessary for TRNG?
35813611
s->aess_state.command_bh = aio_bh_new(qemu_get_aio_context(), aess_handle_cmd_bh, &s->aess_state);
35823612
s->pka_state.command_bh = aio_bh_new(qemu_get_aio_context(), pka_handle_cmd_bh, &s->pka_state); // unused yet

include/hw/arm/apple-silicon/sep.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ typedef struct {
8181
typedef struct {
8282
AppleSEPState *sep;
8383
QEMUBH *command_bh;
84+
QemuMutex lock;
8485
uint32_t chip_id;
8586
uint32_t status; // 0x4
8687
uint32_t command; // 0x8
@@ -128,6 +129,7 @@ typedef struct {
128129
typedef struct {
129130
AppleSEPState *sep;
130131
QEMUBH *command_bh;
132+
QemuMutex lock;
131133
uint32_t command; // 0x0
132134
uint32_t status0; // 0x4
133135
uint32_t status_in0; // 0x8

0 commit comments

Comments
 (0)