1 /* Copyright (c) (2021-2023) Apple Inc. All rights reserved. 2 * 3 * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which 4 * is contained in the License.txt file distributed with corecrypto) and only to 5 * people who accept that license. IMPORTANT: Any license rights granted to you by 6 * Apple Inc. (if any) are limited to internal use within your organization only on 7 * devices and computers you own or control, for the sole purpose of verifying the 8 * security characteristics and correct functioning of the Apple Software. You may 9 * not, directly or indirectly, redistribute the Apple Software or any portions thereof. 10 */ 11 12 #ifndef _CORECRYPTO_CC_LOCK_H_ 13 #define _CORECRYPTO_CC_LOCK_H_ 14 15 #include <corecrypto/cc_priv.h> 16 17 typedef struct cc_lock_ctx cc_lock_ctx_t; 18 int cc_lock_init(cc_lock_ctx_t *ctx, const char *group_name); 19 20 #if defined(_WIN32) 21 #include <windows.h> 22 #endif 23 24 //============================================================================== 25 // 26 // corecrypto support for multithreaded environments 27 // 28 // This part of corecrypto is OS dependent and it serves two purposes 29 // a) It allows multiple threads to use ccrng() 30 // b) If the process is forked, it reseeds the ccrng, so that parent and child 31 // state differs and generate different random numbers 32 //============================================================================== 33 34 #if CC_USE_L4 || CC_USE_SEPROM || CC_RTKIT || CC_RTKITROM 35 #define CC_LOCK_IMPL_NULL 1 36 #define CC_LOCK_IMPL_POSIX 0 37 #define CC_LOCK_IMPL_USER 0 38 #define CC_LOCK_IMPL_WIN 0 39 #define CC_LOCK_IMPL_KERNEL 0 40 #define CC_LOCK_IMPL_SGX 0 41 #elif CC_LINUX && CC_KERNEL && CC_DARWIN && CORECRYPTO_SIMULATE_POSIX_ENVIRONMENT 42 // this is only to allow linux development on macOS. It is not useful in practice. 43 #define CC_LOCK_IMPL_NULL 0 44 #define CC_LOCK_IMPL_POSIX 0 45 #define CC_LOCK_IMPL_USER 0 46 #define CC_LOCK_IMPL_WIN 0 47 #define CC_LOCK_IMPL_KERNEL 1 48 #define CC_LOCK_IMPL_SGX 0 49 #elif CC_DARWIN && !CC_KERNEL && !CC_EFI && CC_INTERNAL_SDK 50 // For Apple OSs (macOS, iOS, watchOS, tvOS), except kernel, L4 and EFI 51 #define CC_LOCK_IMPL_NULL 0 52 #define CC_LOCK_IMPL_POSIX 0 53 #define CC_LOCK_IMPL_USER 1 54 #define CC_LOCK_IMPL_WIN 0 55 #define CC_LOCK_IMPL_KERNEL 0 56 #define CC_LOCK_IMPL_SGX 0 57 #elif CC_DARWIN && CC_KERNEL // For the Apple Kernel 58 #define CC_LOCK_IMPL_NULL 0 59 #define CC_LOCK_IMPL_POSIX 0 60 #define CC_LOCK_IMPL_USER 0 61 #define CC_LOCK_IMPL_WIN 0 62 #define CC_LOCK_IMPL_KERNEL 1 63 #define CC_LOCK_IMPL_SGX 0 64 #elif defined(_WIN32) // for Windows 65 #define CC_LOCK_IMPL_NULL 0 66 #define CC_LOCK_IMPL_POSIX 0 67 #define CC_LOCK_IMPL_USER 0 68 #define CC_LOCK_IMPL_WIN 1 69 #define CC_LOCK_IMPL_KERNEL 0 70 #define CC_LOCK_IMPL_SGX 0 71 #elif CC_SGX // for SGX Enclave 72 #define CC_LOCK_IMPL_NULL 0 73 #define CC_LOCK_IMPL_POSIX 0 74 #define CC_LOCK_IMPL_USER 0 75 #define CC_LOCK_IMPL_WIN 0 76 #define CC_LOCK_IMPL_KERNEL 0 77 #define CC_LOCK_IMPL_SGX 1 78 #elif CC_LINUX || !CC_INTERNAL_SDK // for systems that support pthread, such as Linux 79 #define CC_LOCK_IMPL_NULL 0 80 #define CC_LOCK_IMPL_POSIX 1 81 #define CC_LOCK_IMPL_USER 0 82 #define CC_LOCK_IMPL_WIN 0 83 #define CC_LOCK_IMPL_KERNEL 0 84 #define CC_LOCK_IMPL_SGX 0 85 #else 86 #error No multithread environment defined for cc_lock. 87 #endif 88 89 #if CC_LOCK_IMPL_NULL 90 91 #define CC_LOCK_LOCK(lock_ctx) cc_try_abort("CC_LOCK_LOCK not implemented") 92 #define CC_LOCK_TRYLOCK(lock_ctx) cc_try_abort("CC_LOCK_TRYLOCK not implemented") 93 #define CC_LOCK_UNLOCK(lock_ctx) cc_try_abort("CC_LOCK_UNLOCK not implemented") 94 #define CC_LOCK_ASSERT(lock_ctx) cc_try_abort("CC_LOCK_ASSERT not implemented") 95 96 struct cc_lock_ctx { 97 }; 98 99 //------------------------------------------------------------------------------ 100 // os/lock library, Apple userland 101 //------------------------------------------------------------------------------ 102 #elif CC_LOCK_IMPL_USER 103 #include <pthread.h> 104 #include <os/lock.h> 105 106 #define CC_LOCK_LOCK(lock_ctx) os_unfair_lock_lock(&(lock_ctx)->lock) 107 #define CC_LOCK_TRYLOCK(lock_ctx) os_unfair_lock_trylock(&(lock_ctx)->lock) 108 #define CC_LOCK_UNLOCK(lock_ctx) os_unfair_lock_unlock(&(lock_ctx)->lock) 109 #define CC_LOCK_ASSERT(lock_ctx) os_unfair_lock_assert_owner(&(lock_ctx)->lock) 110 111 struct cc_lock_ctx { 112 os_unfair_lock lock; 113 }; 114 115 //------------------------------------------------------------------------------ 116 // POSIX library, Linux 117 //------------------------------------------------------------------------------ 118 #elif CC_LOCK_IMPL_POSIX 119 #include <pthread.h> 120 121 #define CC_LOCK_LOCK(lock_ctx) (pthread_mutex_lock(&(lock_ctx)->mutex) == 0) 122 #define CC_LOCK_TRYLOCK(lock_ctx) (pthread_mutex_trylock(&(lock_ctx)->mutex) == 0) 123 #define CC_LOCK_UNLOCK(lock_ctx) (pthread_mutex_unlock(&(lock_ctx)->mutex) == 0) 124 #define CC_LOCK_ASSERT(lock_ctx) do { } while (0) 125 126 struct cc_lock_ctx { 127 pthread_mutex_t mutex; 128 }; 129 130 //------------------------------------------------------------------------------ 131 // Kext, XNU 132 //------------------------------------------------------------------------------ 133 #elif CC_LOCK_IMPL_KERNEL 134 135 #include <kern/locks.h> 136 #define CC_LOCK_LOCK(lock_ctx) lck_mtx_lock((lock_ctx)->mutex) 137 #define CC_LOCK_TRYLOCK(lock_ctx) lck_mtx_try_lock((lock_ctx)->mutex) 138 #define CC_LOCK_UNLOCK(lock_ctx) lck_mtx_unlock((lock_ctx)->mutex) 139 #define CC_LOCK_ASSERT(lock_ctx) lck_mtx_assert((lock_ctx)->mutex, LCK_MTX_ASSERT_OWNED); 140 141 struct cc_lock_ctx { 142 lck_mtx_t *mutex; 143 lck_grp_t *group; 144 }; 145 146 //------------------------------------------------------------------------------ 147 // Windows 148 //------------------------------------------------------------------------------ 149 #elif CC_LOCK_IMPL_WIN 150 151 #define CC_LOCK_LOCK(lock_ctx) \ 152 if (WaitForSingleObject((lock_ctx)->hMutex, INFINITE) != WAIT_OBJECT_0) \ 153 return CCERR_INTERNAL; 154 #define CC_LOCK_UNLOCK(lock_ctx) ReleaseMutex((lock_ctx)->hMutex) 155 #define CC_LOCK_ASSERT(lock_ctx) do { } while (0) 156 157 struct cc_lock_ctx { 158 HANDLE hMutex; 159 }; 160 161 //------------------------------------------------------------------------------ 162 // SGX 163 //------------------------------------------------------------------------------ 164 #elif CC_LOCK_IMPL_SGX 165 // Avoid an OCALL in the middle of RNG routines: use spinlocks instead of mutexes. 166 #include <pthread.h> 167 168 #define CC_LOCK_LOCK(lock_ctx) pthread_spin_lock(&(lock_ctx)->lock) 169 #define CC_LOCK_UNLOCK(lock_ctx) pthread_spin_unlock(&(lock_ctx)->lock) 170 #define CC_LOCK_ASSERT(lock_ctx) do { } while (0) 171 172 struct cc_lock_ctx { 173 pthread_spinlock_t lock; 174 }; 175 176 //------------------------------------------------------------------------------ 177 // default 178 //------------------------------------------------------------------------------ 179 #else 180 #error "cc_lock is not implemented." 181 #endif /* CC_LOCK_IMPL_USER */ 182 183 #endif /* _CORECRYPTO_CC_LOCK_H_ */ 184