Files
intel-linux-sgx/sdk/trts/linux/trts_mitigation.S
Li, Xun 9fafc27e8f Linux 2.25 Open Source Gold Release
Upgraded to OpenSSL 3.0.14.
Upgraded Intel(R) Integrated Performance Primitives (IPP) Cryptography library to version
  2021.12.1.
Supported FIPS 140-3 Certifiable IPP Crypto based Trusted Library.
Upgraded Intel SGX Architecture Enclaves based on new IPP crypto library.
Upgraded Intel DCAP Quote Verification Enclave to integrate OpenSSL/SgxSSL 3.0.14.
Removed Intel DCAP PCCS from repository.
Added Ubuntu* 24.04 LTS 64-bit Server support.
Fixed bug.

Note that PCCS is not available from this release. Please follow DCAP installation guide to use
`PCCSAdminTool` to retrieve the attestation collaterals or use old version PCCS.

Signed-off-by: Li, Xun <xun.li@intel.com>
2024-09-26 15:34:56 +08:00

419 lines
16 KiB
ArmAsm

/*
* Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Generates code that consumes `n` cycles by repeatedly moving from register
// `r` to itself.
.macro CYCLE_DELAY n r
lea (\r), \r
.if \n-1
CYCLE_DELAY "(\n-1)" \r
.endif
.endm
.data
.align 0x1000 /* 4KB */
.globl aex_notify_c3_cache
aex_notify_c3_cache:
.space 0x1000 /* 4KB */
/*
* Description:
* The file provides mitigations for SGX-Step
*/
.file "trts_mitigation.S"
#include "trts_pic.h"
#include "../trts_mitigation.h"
/* .text */
.section .nipx,"ax",@progbits
/*
* -------------------------------------------------------------------------
* extern "C"
* void constant_time_apply_sgxstep_mitigation_and_continue_execution(
* sgx_exception_info_t *info,
* uintptr_t ssa_aexnotify_addr,
* uintptr_t stack_tickle_pages,
* uintptr_t code_tickle_page,
* uintptr_t data_tickle_address,
* uintptr_t c3_byte_address);
*
* Function: constant_time_apply_sgxstep_mitigation_and_continue_execution
* Mitigate SGX-Step and return to the point at which the most recent
* interrupt/exception occurred.
* Parameters:
* - info: pointer to the SGX exception info for the most recent
* interrupt/exception
* - ssa_aexnotify_addr: address of the SSA[0].GPRSGX.AEXNOTIFY byte
* - stack_tickle_pages: Base address of stack page(s) to tickle
* - code_tickle_page: Base address of code page to tickle
* - data_tickle_address: address of data memory to tickle
* - c3_byte_address: Address of a c3 byte in code_tickle_page
* There are three additional "implicit" parameters to this function:
* 1. The low-order bit of `stack_tickle_pages` is 1 if a second stack
* page should be tickled (specifically, the stack page immediately
* below the page specified in the upper bits)
* 2. Bit 0 of `code_tickle_page` is 1 if `data_tickle_address`
* is writable, and therefore should be tested for write permissions
* by the mitigation
* 3. Bit 4 of `code_tickle_page` is 1 if the cycle delay
* should be added to the mitigation
*
* Stack:
* bottom of stack -> ---------------------------
* | Lower frame(s) |
* ---------------------------
* rsp of main flow ---+ | Stack frame of the "main |
* == | | flow" function that was |
* rsp @mitigation_begin -> | interrupted |<--+-(irq mitigation)
* --------------------------- |
* | ... |<--+-(irq c3)
* | red zone (128 bytes) | |
* | ... | |
* +- --------------------------- |
* +-|-| rsvd main-flow RIP |-1 |
* | | | rsvd main-flow RAX |-2 |
* | | | rsvd main-flow RCX |-3 |
* (main-flow regs that | | | rsvd main-flow RDX |-4 |
* will be reset in | | | rsvd main-flow RBX |-5 |
* ct_restore_state) | | | rsvd main-flow RBP |-6 |
* | | | rsvd main-flow RSI |-7 |
* | | | rsvd main-flow RDI |-8 |
* +-|-| rsvd main-flow -8(rsp) |-9 |
* (this whole rsvd area | --------------------------- |
* is persistent and will | | ... | |
* not be touched by | | padding for alignment | |
* stage-1/2 handlers) +-| ... | |
* +-- --------------------------- |
* | | exception_type | |
* | | exception_vec | |
* | | pre-irq RIP |17 |
* | | pre-irq RFLAGS |16 |
* | | pre-irq R15 |15 |
* (pre-irq CPU state | | pre-irq R14 |14 |
* prepared by stage-1 | | pre-irq R13 |13 |
* handler in | | pre-irq R12 |12 |
* trts_handle_exception)| | pre-irq R11 |11 |
* | | pre-irq R10 |10 |
* | | pre-irq R9 |9 |
* | | pre-irq R8 |8 |
* | | pre-irq RDI |7 |
* | | pre-irq RSI |6 |
* | | pre-irq RBP |5 |
* | | pre-irq RSP |4--+
* | | pre-irq RBX |3
* | | pre-irq RDX |2
* | | pre-irq RCX |1
* rdi @entry -> | pre-irq RAX |0
* +-- ---------------------------|
* rsp @second_phase -> | pre-irq RIP (for dbg) |
* ---------------------------|
* | Stack frame of stage-2 |
* | internal_handle_exception |
* rsp @entry -> | ... |
* ---------------------------
* -------------------------------------------------------------------------
*/
#define RSVD_BOTTOM (-RED_ZONE_SIZE-0*SE_WORDSIZE)
#define RSVD_RIP_OFFSET (-RED_ZONE_SIZE-1*SE_WORDSIZE)
#define RSVD_RAX_OFFSET (-RED_ZONE_SIZE-2*SE_WORDSIZE)
#define RSVD_RCX_OFFSET (-RED_ZONE_SIZE-3*SE_WORDSIZE)
#define RSVD_RDX_OFFSET (-RED_ZONE_SIZE-4*SE_WORDSIZE)
#define RSVD_RBX_OFFSET (-RED_ZONE_SIZE-5*SE_WORDSIZE)
#define RSVD_RBP_OFFSET (-RED_ZONE_SIZE-6*SE_WORDSIZE)
#define RSVD_RSI_OFFSET (-RED_ZONE_SIZE-7*SE_WORDSIZE)
#define RSVD_RDI_OFFSET (-RED_ZONE_SIZE-8*SE_WORDSIZE)
#define RSVD_REDZONE_WORD_OFFSET (-RED_ZONE_SIZE-9*SE_WORDSIZE)
#define RSVD_TOP (-RED_ZONE_SIZE-9*SE_WORDSIZE)
#if RSVD_SIZE_OF_MITIGATION_STACK_AREA != (RSVD_BOTTOM-RSVD_TOP)
#error "Malformed reserved mitigation stack area"
#endif
#define INFO_RAX_OFFSET (0*SE_WORDSIZE)
#define INFO_RCX_OFFSET (1*SE_WORDSIZE)
#define INFO_RDX_OFFSET (2*SE_WORDSIZE)
#define INFO_RBX_OFFSET (3*SE_WORDSIZE)
#define INFO_RSP_OFFSET (4*SE_WORDSIZE)
#define INFO_RBP_OFFSET (5*SE_WORDSIZE)
#define INFO_RSI_OFFSET (6*SE_WORDSIZE)
#define INFO_RDI_OFFSET (7*SE_WORDSIZE)
#define INFO_R8_OFFSET (8*SE_WORDSIZE)
#define INFO_R9_OFFSET (9*SE_WORDSIZE)
#define INFO_R10_OFFSET (10*SE_WORDSIZE)
#define INFO_R11_OFFSET (11*SE_WORDSIZE)
#define INFO_R12_OFFSET (12*SE_WORDSIZE)
#define INFO_R13_OFFSET (13*SE_WORDSIZE)
#define INFO_R14_OFFSET (14*SE_WORDSIZE)
#define INFO_R15_OFFSET (15*SE_WORDSIZE)
#define INFO_FLAGS_OFFSET (16*SE_WORDSIZE)
#define INFO_RIP_OFFSET (17*SE_WORDSIZE)
# Returns the enclave application resumption point if the AEX occurred within
# the mitigation or at __ct_mitigation_ret. If the AEX occurred during the
# mitigation at a RET instruction within the enclave application called by
# .ct_check_execute, then cselect_mitigation_rip() will return the address of
# that RET. Thus, the returned RIP will always point within the originally
# interrupted enclave application page.
DECLARE_LOCAL_FUNC cselect_mitigation_rip
# rdi: info
mov INFO_RIP_OFFSET(%rdi), %rax # rax: pre-irq rip
mov INFO_RSP_OFFSET(%rdi), %rcx # rcx: pre-irq rsp
lea_pic __ct_mitigation_ret, %rsi
cmp %rsi, %rax
lea 8(%rcx), %rsi
# set rcx = IRQ in __ct_mitigation_ret ? original main-flow rsp : pre-irq rsp
cmove %rsi, %rcx
lea_pic __ct_mitigation_ret, %rdx
sub %rax, %rdx
# set CF=1 (B) if IRQ in mitigation (including __ct_mitigation_ret)
cmp $(.ct_aexnotify_end - .ct_mitigation_begin), %rdx
# set rax = irq in mitigation ? original main-flow rip : pre-irq rip
cmovb RSVD_RIP_OFFSET(%rcx), %rax
ret
END_FUNC
# If interrupt happened during execution of the atomic mitigation stub
# (including any C3 calls from ct_check_execute), restore clobbered
# enclave application registers from the persistent reserved area on the
# stack into the info struct parameter.
DECLARE_LOCAL_FUNC cselect_mitigation_regs
# rdi: info
# rsi: saved_rip
# rdx: c3_byte_address
mov INFO_RIP_OFFSET(%rdi), %rax
mov INFO_RSP_OFFSET(%rdi), %rcx
# Set r8b=1 if saved_rip=c3_byte_address
cmp %rsi, %rdx
sete %r8b
# Set r9b=1 if info->rip=__ct_mitigation_ret
lea_pic __ct_mitigation_ret, %rdx
cmp %rax, %rdx
sete %r9b
# Set r10b=1 if *info->rsp=.ct_check_execute_post
lea_pic .ct_check_execute_post, %rdx
cmp (%rcx), %rdx
sete %r10b
# Set r8b=1 if (*info->rsp=.ct_check_execute_post)
# and ((saved_rip=c3_byte_address) or (info->rip=__ct_mitigation_ret))
or %r9b, %r8b
and %r10b, %r8b
# Pop the return address if r8b=1
lea 8(%rcx), %rdx
cmovnz %rdx, %rcx
mov %rcx, INFO_RSP_OFFSET(%rdi)
# Set r9b=1 if the mitigation was interrupted, but not at a RET
lea_pic .ct_mitigation_end, %rdx
sub %rax, %rdx
cmp $(.ct_mitigation_end - .ct_mitigation_begin + 1), %rdx
setb %r9b
# If the mitigation was interrupted, restore clobbered registers from the
# reserved area on the stack.
or %r9b, %r8b
mov INFO_RIP_OFFSET(%rdi), %rax
cmovnz RSVD_RIP_OFFSET(%rcx), %rax
mov %rax, RSVD_RIP_OFFSET(%rcx)
mov %rax, INFO_RIP_OFFSET(%rdi)
mov INFO_RAX_OFFSET(%rdi), %rax
cmovnz RSVD_RAX_OFFSET(%rcx), %rax
mov %rax, RSVD_RAX_OFFSET(%rcx)
mov %rax, INFO_RAX_OFFSET(%rdi)
mov INFO_RCX_OFFSET(%rdi), %rax
cmovnz RSVD_RCX_OFFSET(%rcx), %rax
mov %rax, RSVD_RCX_OFFSET(%rcx)
mov %rax, INFO_RCX_OFFSET(%rdi)
mov INFO_RDX_OFFSET(%rdi), %rax
cmovnz RSVD_RDX_OFFSET(%rcx), %rax
mov %rax, RSVD_RDX_OFFSET(%rcx)
mov %rax, INFO_RDX_OFFSET(%rdi)
mov INFO_RBX_OFFSET(%rdi), %rax
cmovnz RSVD_RBX_OFFSET(%rcx), %rax
mov %rax, RSVD_RBX_OFFSET(%rcx)
mov %rax, INFO_RBX_OFFSET(%rdi)
mov INFO_RBP_OFFSET(%rdi), %rax
cmovnz RSVD_RBP_OFFSET(%rcx), %rax
mov %rax, RSVD_RBP_OFFSET(%rcx)
mov %rax, INFO_RBP_OFFSET(%rdi)
mov INFO_RSI_OFFSET(%rdi), %rax
cmovnz RSVD_RSI_OFFSET(%rcx), %rax
mov %rax, RSVD_RSI_OFFSET(%rcx)
mov %rax, INFO_RSI_OFFSET(%rdi)
mov INFO_RDI_OFFSET(%rdi), %rax
cmovnz RSVD_RDI_OFFSET(%rcx), %rax
mov %rax, RSVD_RDI_OFFSET(%rcx)
mov %rax, INFO_RDI_OFFSET(%rdi)
# If the mitigation was interrupted, restore the first q/dword of the red
# zone from the reserved area; otherwise save it to the reserved area
mov -SE_WORDSIZE(%rcx), %rax
cmovnz RSVD_REDZONE_WORD_OFFSET(%rcx), %rax
mov %rax, RSVD_REDZONE_WORD_OFFSET(%rcx)
ret
END_FUNC
DECLARE_LOCAL_FUNC constant_time_apply_sgxstep_mitigation_and_continue_execution
# rdi: info
# rsi: address of the AEX-Notify-enabling byte
# rdx: stack_tickle_pages
# rcx: code_tickle_page
# r8: data_tickle_address
# r9: c3_byte_address
mov %r8, %rbx
mov %r9, %rbp
mov INFO_R8_OFFSET(%rdi), %r8
mov INFO_R9_OFFSET(%rdi), %r9
mov INFO_R10_OFFSET(%rdi), %r10
mov INFO_R11_OFFSET(%rdi), %r11
mov INFO_R12_OFFSET(%rdi), %r12
mov INFO_R13_OFFSET(%rdi), %r13
mov INFO_R14_OFFSET(%rdi), %r14
mov INFO_R15_OFFSET(%rdi), %r15
/* NOTE: moving rsp upwards as a scratchpad register discards any data at lower
* addresses (i.e., these may be overwritten by nested exception handlers), but
* the stage-1 handler will always safeguard a 128-byte red zone under the
* interrupted stack pointer. Thus, the code below is safe:
* INFO_FLAGS_OFFSET-INFO_RSP_OFFSET = 12*8 = 96 < 128-byte ABI red zone.
*/
lea INFO_FLAGS_OFFSET(%rdi), %rsp
popf
mov INFO_RSP_OFFSET(%rdi), %rsp /* rsp: pre-irq rsp */
mov %rdx, %rdi
# NOTHING AFTER THIS POINT CAN MODIFY EFLAGS/RFLAGS
################################################################################
# BEGIN MITIGATION CODE
################################################################################
# rdi: stack_tickle_pages
# rsi: address of the AEX-Notify-enabling byte
# rdx: unused (will be clobbered)
# rcx: code_tickle_page
# rax: unused (will be clobbered)
# rbx: data_tickle_address
# rbp: c3_byte_address
#define MITIGATION_CODE_ALIGNMENT 0x200
.align MITIGATION_CODE_ALIGNMENT
# Enable AEX Notify
.ct_enable_aexnotify:
movb $1, (%rsi)
.ct_mitigation_begin:
mov RSVD_REDZONE_WORD_OFFSET(%rsp), %rsi
lfence
# Set up the stack tickles
movzx %dil, %edx # Bit 0 in %rdi indicates whether a second stack page can be tickled
mov $0, %dil
mov $12, %eax
shlx %rax, %rdx, %rdx
lea (%rdi,%rdx), %rdx
.ct_check_write:
mov %rcx, %rax
mov $63, %ecx
shlx %rcx, %rax, %rcx # Bit 0 in %rax indicates whether data_tickle_address can be written
jrcxz .ct_clear_low_bits_of_rbx
lea -1(%rax), %rax # Clear bit 0 in %rax
movb (%rbx), %cl
movb %cl, (%rbx) # Will fault if the data page is not writable
.ct_clear_low_bits_of_rbx:
movl $12, %ecx
shrx %rcx, %rbx, %rbx
shlx %rcx, %rbx, %rbx
.ct_check_execute:
call *%rbp
.ct_check_execute_post:
mov RSVD_RBP_OFFSET(%rsp), %rbp
mov %rsi, -SE_WORDSIZE(%rsp) # restore the first q/dword of the red zone
# Load all working set cache lines and warm the TLB entries
mov $0x1000, %ecx
.align 0x10
.ct_warm_caches_and_tlbs:
lea -0x40(%ecx), %ecx
mov (%rax, %rcx), %esi # code page tickle
mov (%rdi, %rcx), %esi # stack page 1 tickle
mov (%rdx, %rcx), %esi # stack page 2 tickle
mov (%rbx, %rcx), %esi # data tickle
jrcxz .ct_restore_state
jmp .ct_warm_caches_and_tlbs # loops 64 times
.ct_restore_state:
movzx %al, %ecx # Bit 4 of %al indicates whether cycles should be added
mov RSVD_RDI_OFFSET(%rsp), %rdi
mov RSVD_RSI_OFFSET(%rsp), %rsi
mov RSVD_RBX_OFFSET(%rsp), %rbx
mov RSVD_RDX_OFFSET(%rsp), %rdx
mov RSVD_RAX_OFFSET(%rsp), %rax
# Inject random cycle noise
jrcxz .ct_restore_rcx
CYCLE_DELAY 20, %rsp
.ct_restore_rcx:
mov RSVD_RCX_OFFSET(%rsp), %rcx
.ct_mitigation_end:
jmp *RSVD_RIP_OFFSET(%rsp)
.global __ct_mitigation_ret
__ct_mitigation_ret:
ret
END_FUNC
.ct_aexnotify_end:
.sect _to_be_discarded, "e", @nobits
.space MITIGATION_CODE_ALIGNMENT - (.ct_aexnotify_end - .ct_enable_aexnotify)
.previous