Skip to content
Open
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
1 change: 1 addition & 0 deletions CREDITS.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ Ziqiao Kong (lazymio): uc_context_free() API and various bug fix & improvement.
Sven Almgren (blindmatrix): bug fix
Chenxu Wu (kabeor): Documentation
Philipp Takacs: virtual tlb, memory snapshots
Daniel Roethlisberger (droe): ARM64 fixes & improvements
9 changes: 9 additions & 0 deletions bindings/dotnet/UnicornEngine/Const/Arm64.fs
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,12 @@ module Arm64 =
let UC_ARM64_INS_WFI = 5
let UC_ARM64_INS_ENDING = 6

// ARM64 PAuth keys

let UC_ARM64_PAUTH_KEY_IA = 0
let UC_ARM64_PAUTH_KEY_IB = 1
let UC_ARM64_PAUTH_KEY_DA = 2
let UC_ARM64_PAUTH_KEY_DB = 3
let UC_ARM64_PAUTH_KEY_GA = 4
let UC_ARM64_PAUTH_KEY_ENDING = 5

3 changes: 3 additions & 0 deletions bindings/dotnet/UnicornEngine/Const/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ module Common =
let UC_CTL_TLB_TYPE = 12
let UC_CTL_TCG_BUFFER_SIZE = 13
let UC_CTL_CONTEXT_MODE = 14
let UC_CTL_PAUTH_SIGN = 15
let UC_CTL_PAUTH_STRIP = 16
let UC_CTL_PAUTH_AUTH = 17
let UC_CTL_CONTEXT_CPU = 1
let UC_CTL_CONTEXT_MEMORY = 2

9 changes: 9 additions & 0 deletions bindings/go/unicorn/arm64_const.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,13 @@ const (
ARM64_INS_SYSL = 4
ARM64_INS_WFI = 5
ARM64_INS_ENDING = 6

// ARM64 PAuth keys

ARM64_PAUTH_KEY_IA = 0
ARM64_PAUTH_KEY_IB = 1
ARM64_PAUTH_KEY_DA = 2
ARM64_PAUTH_KEY_DB = 3
ARM64_PAUTH_KEY_GA = 4
ARM64_PAUTH_KEY_ENDING = 5
)
3 changes: 3 additions & 0 deletions bindings/go/unicorn/unicorn_const.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ const (
CTL_TLB_TYPE = 12
CTL_TCG_BUFFER_SIZE = 13
CTL_CONTEXT_MODE = 14
CTL_PAUTH_SIGN = 15
CTL_PAUTH_STRIP = 16
CTL_PAUTH_AUTH = 17
CTL_CONTEXT_CPU = 1
CTL_CONTEXT_MEMORY = 2
)
9 changes: 9 additions & 0 deletions bindings/java/src/main/java/unicorn/Arm64Const.java
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,13 @@ public interface Arm64Const {
public static final int UC_ARM64_INS_WFI = 5;
public static final int UC_ARM64_INS_ENDING = 6;

// ARM64 PAuth keys

public static final int UC_ARM64_PAUTH_KEY_IA = 0;
public static final int UC_ARM64_PAUTH_KEY_IB = 1;
public static final int UC_ARM64_PAUTH_KEY_DA = 2;
public static final int UC_ARM64_PAUTH_KEY_DB = 3;
public static final int UC_ARM64_PAUTH_KEY_GA = 4;
public static final int UC_ARM64_PAUTH_KEY_ENDING = 5;

}
3 changes: 3 additions & 0 deletions bindings/java/src/main/java/unicorn/UnicornConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ public interface UnicornConst {
public static final int UC_CTL_TLB_TYPE = 12;
public static final int UC_CTL_TCG_BUFFER_SIZE = 13;
public static final int UC_CTL_CONTEXT_MODE = 14;
public static final int UC_CTL_PAUTH_SIGN = 15;
public static final int UC_CTL_PAUTH_STRIP = 16;
public static final int UC_CTL_PAUTH_AUTH = 17;
public static final int UC_CTL_CONTEXT_CPU = 1;
public static final int UC_CTL_CONTEXT_MEMORY = 2;

Expand Down
9 changes: 9 additions & 0 deletions bindings/pascal/unicorn/Arm64Const.pas
Original file line number Diff line number Diff line change
Expand Up @@ -338,5 +338,14 @@ interface
UC_ARM64_INS_WFI = 5;
UC_ARM64_INS_ENDING = 6;

// ARM64 PAuth keys

UC_ARM64_PAUTH_KEY_IA = 0;
UC_ARM64_PAUTH_KEY_IB = 1;
UC_ARM64_PAUTH_KEY_DA = 2;
UC_ARM64_PAUTH_KEY_DB = 3;
UC_ARM64_PAUTH_KEY_GA = 4;
UC_ARM64_PAUTH_KEY_ENDING = 5;

implementation
end.
3 changes: 3 additions & 0 deletions bindings/pascal/unicorn/UnicornConst.pas
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ interface
UC_CTL_TLB_TYPE = 12;
UC_CTL_TCG_BUFFER_SIZE = 13;
UC_CTL_CONTEXT_MODE = 14;
UC_CTL_PAUTH_SIGN = 15;
UC_CTL_PAUTH_STRIP = 16;
UC_CTL_PAUTH_AUTH = 17;
UC_CTL_CONTEXT_CPU = 1;
UC_CTL_CONTEXT_MEMORY = 2;

Expand Down
9 changes: 9 additions & 0 deletions bindings/python/unicorn/arm64_const.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,3 +332,12 @@
UC_ARM64_INS_SYSL = 4
UC_ARM64_INS_WFI = 5
UC_ARM64_INS_ENDING = 6

# ARM64 PAuth keys

UC_ARM64_PAUTH_KEY_IA = 0
UC_ARM64_PAUTH_KEY_IB = 1
UC_ARM64_PAUTH_KEY_DA = 2
UC_ARM64_PAUTH_KEY_DB = 3
UC_ARM64_PAUTH_KEY_GA = 4
UC_ARM64_PAUTH_KEY_ENDING = 5
3 changes: 3 additions & 0 deletions bindings/python/unicorn/unicorn_const.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,8 @@
UC_CTL_TLB_TYPE = 12
UC_CTL_TCG_BUFFER_SIZE = 13
UC_CTL_CONTEXT_MODE = 14
UC_CTL_PAUTH_SIGN = 15
UC_CTL_PAUTH_STRIP = 16
UC_CTL_PAUTH_AUTH = 17
UC_CTL_CONTEXT_CPU = 1
UC_CTL_CONTEXT_MEMORY = 2
65 changes: 58 additions & 7 deletions bindings/python/unicorn/unicorn_py3/unicorn.py
Original file line number Diff line number Diff line change
Expand Up @@ -1253,16 +1253,15 @@ def __ctl_w(self, ctl: int, *args: Arg):

self.ctl(ctl, uc.UC_CTL_IO_WRITE, *cargs)

def __ctl_wr(self, ctl: int, arg0: Arg, arg1: Arg):
atype, avalue = arg0
carg0 = atype(avalue)
def __ctl_wr(self, ctl: int, *args: Arg):
cargs = (atype(avalue) for atype, avalue in args[:-1])

atype, _ = arg1
carg1 = atype()
atype, _ = args[-1]
cretv = atype()

self.ctl(ctl, uc.UC_CTL_IO_READ_WRITE, carg0, ctypes.byref(carg1))
self.ctl(ctl, uc.UC_CTL_IO_READ_WRITE, *cargs, ctypes.byref(cretv))

return carg1.value
return cretv.value

def ctl_get_mode(self) -> int:
"""Retrieve current processor mode.
Expand Down Expand Up @@ -1475,6 +1474,58 @@ def ctl_set_tcg_buffer_size(self, size: int) -> None:
(ctypes.c_uint32, size)
)

def ctl_pauth_sign(self, ptr: int, key: int, diversifier: int) -> int:
"""Sign a pointer with a key and discriminator.

Args:
ptr: pointer to sign
key: architecture-specific constant indicating the key to use
diversifier: discriminator to use

Returns: the signed pointer
"""

return self.__ctl_wr(uc.UC_CTL_PAUTH_SIGN,
(ctypes.c_uint64, ptr),
(ctypes.c_uint32, key),
(ctypes.c_uint64, diversifier),
(ctypes.c_uint64, None),
)

def ctl_pauth_strip(self, ptr: int, key: int) -> int:
"""Strip the PAC from a possibly signed pointer.

Args:
ptr: pointer to strip PAC from
key: architecture-specific constant indicating the key to use

Returns: the stripped pointer
"""

return self.__ctl_wr(uc.UC_CTL_PAUTH_STRIP,
(ctypes.c_uint64, ptr),
(ctypes.c_uint32, key),
(ctypes.c_uint64, None),
)

def ctl_pauth_auth(self, ptr: int, key: int, diversifier: int) -> bool:
"""Authenticate a pointer with a key and discriminator.

Args:
ptr: signed pointer to authenticate
key: architecture-specific constant indicating the key to use
diversifier: discriminator to use

Returns: True if signature is valid, False othewise
"""

return self.__ctl_wr(uc.UC_CTL_PAUTH_AUTH,
(ctypes.c_uint64, ptr),
(ctypes.c_uint32, key),
(ctypes.c_uint64, diversifier),
(ctypes.c_bool, None),
)


class UcContext(RegStateManager):
"""Unicorn internal context.
Expand Down
9 changes: 9 additions & 0 deletions bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,13 @@ module UnicornEngine
UC_ARM64_INS_SYSL = 4
UC_ARM64_INS_WFI = 5
UC_ARM64_INS_ENDING = 6

# ARM64 PAuth keys

UC_ARM64_PAUTH_KEY_IA = 0
UC_ARM64_PAUTH_KEY_IB = 1
UC_ARM64_PAUTH_KEY_DA = 2
UC_ARM64_PAUTH_KEY_DB = 3
UC_ARM64_PAUTH_KEY_GA = 4
UC_ARM64_PAUTH_KEY_ENDING = 5
end
3 changes: 3 additions & 0 deletions bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ module UnicornEngine
UC_CTL_TLB_TYPE = 12
UC_CTL_TCG_BUFFER_SIZE = 13
UC_CTL_CONTEXT_MODE = 14
UC_CTL_PAUTH_SIGN = 15
UC_CTL_PAUTH_STRIP = 16
UC_CTL_PAUTH_AUTH = 17
UC_CTL_CONTEXT_CPU = 1
UC_CTL_CONTEXT_MEMORY = 2
end
9 changes: 9 additions & 0 deletions bindings/zig/unicorn/arm64_const.zig
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,13 @@ pub const arm64Const = enum(c_int) {
ARM64_INS_WFI = 5,
ARM64_INS_ENDING = 6,

// ARM64 PAuth keys

ARM64_PAUTH_KEY_IA = 0,
ARM64_PAUTH_KEY_IB = 1,
ARM64_PAUTH_KEY_DA = 2,
ARM64_PAUTH_KEY_DB = 3,
ARM64_PAUTH_KEY_GA = 4,
ARM64_PAUTH_KEY_ENDING = 5,

};
3 changes: 3 additions & 0 deletions bindings/zig/unicorn/unicorn_const.zig
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ pub const unicornConst = enum(c_int) {
CTL_TLB_TYPE = 12,
CTL_TCG_BUFFER_SIZE = 13,
CTL_CONTEXT_MODE = 14,
CTL_PAUTH_SIGN = 15,
CTL_PAUTH_STRIP = 16,
CTL_PAUTH_AUTH = 17,
CTL_CONTEXT_CPU = 1,
CTL_CONTEXT_MEMORY = 2,

Expand Down
8 changes: 8 additions & 0 deletions include/uc_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ typedef uc_tcg_flush_tlb uc_tb_flush_t;

typedef uc_err (*uc_set_tlb_t)(struct uc_struct *uc, int mode);

// PAuth sign and strip
typedef uc_err (*uc_pauth_sign_t)(struct uc_struct *uc, uint64_t ptr, int key, uint64_t diversifier, uint64_t *signed_ptr);
typedef uc_err (*uc_pauth_strip_t)(struct uc_struct *uc, uint64_t ptr, int key, uint64_t *stripped_ptr);
typedef uc_err (*uc_pauth_auth_t)(struct uc_struct *uc, uint64_t ptr, int key, uint64_t diversifier, bool *valid);

struct hook {
int type; // UC_HOOK_*
int insn; // instruction for HOOK_INSN
Expand Down Expand Up @@ -313,6 +318,9 @@ struct uc_struct {
uc_tb_flush_t tb_flush;
uc_add_inline_hook_t add_inline_hook;
uc_del_inline_hook_t del_inline_hook;
uc_pauth_sign_t pauth_sign;
uc_pauth_strip_t pauth_strip;
uc_pauth_auth_t pauth_auth;

uc_context_size_t context_size;
uc_context_save_t context_save;
Expand Down
10 changes: 10 additions & 0 deletions include/unicorn/arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,16 @@ typedef enum uc_arm64_insn {
UC_ARM64_INS_ENDING
} uc_arm64_insn;

//> ARM64 PAuth keys
typedef enum uc_arm64_pauth_key {
UC_ARM64_PAUTH_KEY_IA = 0,
UC_ARM64_PAUTH_KEY_IB,
UC_ARM64_PAUTH_KEY_DA,
UC_ARM64_PAUTH_KEY_DB,
UC_ARM64_PAUTH_KEY_GA,
UC_ARM64_PAUTH_KEY_ENDING,
} uc_arm64_pauth_key;

#ifdef __cplusplus
}
#endif
Expand Down
46 changes: 46 additions & 0 deletions include/unicorn/unicorn.h
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,46 @@ typedef enum uc_control_type {
// controle if context_save/restore should work with snapshots
// Write: @args = (int)
UC_CTL_CONTEXT_MODE,

// Sign a pointer with a given architecture-specific key and a diversifier
// (also known as modifier, extra data, or discriminator). If the key is
// currently disabled, the operation returns the unsigned ptr.
// ABI-specific string hashing or address blending is up to the caller to
// implement.
//
// Pointer authentication needs to have been set up properly beforehand.
// Depending on architecture, current CPU state may determine pointer
// layout and other aspects of the operation not explicitly specified as
// parameters.
//
// Read/write: @args = (uint64_t ptr, int key, uint64_t diversifier,
// uint64_t *signed_ptr)
UC_CTL_PAUTH_SIGN,

// Strip a possibly signed pointer of all PAC bits without authenticating,
// returning an unsigned pointer.
//
// Pointer authentication needs to have been set up properly beforehand.
// Depending on architecture, current CPU state may determine pointer
// layout and other aspects of the operation not explicitly specified as
// parameters.
//
// Read/write: @args = (uint64_t ptr, int key, uint64_t *stripped_ptr)
UC_CTL_PAUTH_STRIP,

// Authenticate a signed pointer with a given architecture-specific key and
// diversifier (also known as modifier, extra data, or discriminator).
// ABI-specific string hashing or address blending is up to the caller to
// implement.
//
// Pointer authentication needs to have been set up properly beforehand.
// Depending on architecture, current CPU state may determine pointer
// layout and other aspects of the operation not explicitly specified as
// parameters.
//
// Read/write: @args = (uint64_t ptr, int key, uint64_t diversifier,
// bool *valid)
UC_CTL_PAUTH_AUTH,
} uc_control_type;

/*
Expand Down Expand Up @@ -688,6 +728,12 @@ See sample_ctl.c for a detailed example.
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TCG_BUFFER_SIZE, 1), (size))
#define uc_ctl_context_mode(uc, mode) \
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CONTEXT_MODE, 1), (mode))
#define uc_ctl_pauth_sign(uc, ptr, key, diversifier, signed_ptr) \
uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_PAUTH_SIGN, 4), (uint64_t)(ptr), (int)(key), (uint64_t)(diversifier), (uint64_t *)(signed_ptr))
#define uc_ctl_pauth_strip(uc, ptr, key, stripped_ptr) \
uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_PAUTH_STRIP, 3), (uint64_t)(ptr), (int)(key), (uint64_t *)(stripped_ptr))
#define uc_ctl_pauth_auth(uc, ptr, key, diversifier, valid) \
uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_PAUTH_AUTH, 4), (uint64_t)(ptr), (int)(key), (uint64_t)(diversifier), (uint64_t *)(valid))

// Opaque storage for CPU context, used with uc_context_*()
struct uc_context;
Expand Down
30 changes: 30 additions & 0 deletions qemu/target/arm/pauth_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,3 +492,33 @@ uint64_t HELPER(xpacd)(CPUARMState *env, uint64_t a)
{
return pauth_strip(env, a, true);
}

uint64_t _uc_pauth_sign(CPUARMState *env, uint64_t ptr, uint64_t diversifier, uint32_t sctlr_bit, ARMPACKey *key, bool data)
{
int el = arm_current_el(env);
if (!pauth_key_enabled(env, el, sctlr_bit)) {
return ptr;
} else {
return pauth_addpac(env, ptr, diversifier, key, data);
}
}

uint64_t _uc_pauth_sign_ga(CPUARMState *env, uint64_t ptr, uint64_t diversifier)
{
return pauth_computepac(ptr, diversifier, env->keys.apga) & 0xffffffff00000000ull;
}

uint64_t _uc_pauth_strip(CPUARMState *env, uint64_t ptr, bool data)
{
return pauth_strip(env, ptr, data);
}

bool _uc_pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t diversifier, uint32_t sctlr_bit, ARMPACKey *key, bool data)
{
int el = arm_current_el(env);
if (!pauth_key_enabled(env, el, sctlr_bit)) {
return false;
}
uint64_t maybe_corrupted_ptr = pauth_auth(env, ptr, diversifier, key, data, 0);
return maybe_corrupted_ptr == pauth_strip(env, ptr, data);
}
Loading
Loading