1 /* Copyright (c) (2021) 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_LINUX && CC_KERNEL && CC_DARWIN && CORECRYPTO_SIMULATE_POSIX_ENVIRONMENT 35 #define CC_LOCK_IMPL_POSIX 0 // this is only to allow linux development on macOS. It is not useful in practice. 36 #define CC_LOCK_IMPL_USER 0 37 #define CC_LOCK_IMPL_WIN 0 38 #define CC_LOCK_IMPL_KERNEL 1 39 #define CC_LOCK_IMPL_SGX 0 40 #elif CC_DARWIN && !CC_KERNEL && !CC_USE_L4 && \ 41 !CC_EFI && CC_INTERNAL_SDK // For Apple OSs (macOS, iOS, watchOS, tvOS), except kernel, L4 and EFI 42 #define CC_LOCK_IMPL_POSIX 0 43 #define CC_LOCK_IMPL_USER 1 44 #define CC_LOCK_IMPL_WIN 0 45 #define CC_LOCK_IMPL_KERNEL 0 46 #define CC_LOCK_IMPL_SGX 0 47 #elif CC_DARWIN && CC_KERNEL // For the Apple Kernel 48 #define CC_LOCK_IMPL_POSIX 0 49 #define CC_LOCK_IMPL_USER 0 50 #define CC_LOCK_IMPL_WIN 0 51 #define CC_LOCK_IMPL_KERNEL 1 52 #define CC_LOCK_IMPL_SGX 0 53 #elif defined(_WIN32) // for Windows 54 #define CC_LOCK_IMPL_POSIX 0 55 #define CC_LOCK_IMPL_USER 0 56 #define CC_LOCK_IMPL_WIN 1 57 #define CC_LOCK_IMPL_KERNEL 0 58 #define CC_LOCK_IMPL_SGX 0 59 #elif CC_SGX // for SGX Enclave 60 #define CC_LOCK_IMPL_POSIX 0 61 #define CC_LOCK_IMPL_USER 0 62 #define CC_LOCK_IMPL_WIN 0 63 #define CC_LOCK_IMPL_KERNEL 0 64 #define CC_LOCK_IMPL_SGX 1 65 #elif CC_LINUX || !CC_INTERNAL_SDK // for systems that support pthread, such as Linux 66 #define CC_LOCK_IMPL_POSIX 1 67 #define CC_LOCK_IMPL_USER 0 68 #define CC_LOCK_IMPL_WIN 0 69 #define CC_LOCK_IMPL_KERNEL 0 70 #define CC_LOCK_IMPL_SGX 0 71 #else 72 #error No multithread environment defined for cc_lock. 73 #endif 74 75 //------------------------------------------------------------------------------ 76 // os/lock library, Apple userland 77 //------------------------------------------------------------------------------ 78 #if CC_LOCK_IMPL_USER 79 #include <pthread.h> 80 #include <os/lock.h> 81 82 #define CC_LOCK_LOCK(lock_ctx) os_unfair_lock_lock(&(lock_ctx)->lock) 83 #define CC_LOCK_TRYLOCK(lock_ctx) os_unfair_lock_trylock(&(lock_ctx)->lock) 84 #define CC_LOCK_UNLOCK(lock_ctx) os_unfair_lock_unlock(&(lock_ctx)->lock) 85 #define CC_LOCK_ASSERT(lock_ctx) os_unfair_lock_assert_owner(&(lock_ctx)->lock) 86 87 struct cc_lock_ctx { 88 os_unfair_lock lock; 89 }; 90 91 //------------------------------------------------------------------------------ 92 // POSIX library, Linux 93 //------------------------------------------------------------------------------ 94 #elif CC_LOCK_IMPL_POSIX 95 #include <pthread.h> 96 97 #define CC_LOCK_LOCK(lock_ctx) pthread_mutex_lock(&(lock_ctx)->mutex) 98 #define CC_LOCK_TRYLOCK(lock_ctx) pthread_mutex_trylock(&(lock_ctx)->mutex) 99 #define CC_LOCK_UNLOCK(lock_ctx) pthread_mutex_unlock(&(lock_ctx)->mutex) 100 #define CC_LOCK_ASSERT(lock_ctx) 101 102 struct cc_lock_ctx { 103 pthread_mutex_t mutex; 104 }; 105 106 //------------------------------------------------------------------------------ 107 // Kext, XNU 108 //------------------------------------------------------------------------------ 109 #elif CC_LOCK_IMPL_KERNEL 110 111 #include <kern/locks.h> 112 #define CC_LOCK_LOCK(lock_ctx) lck_mtx_lock((lock_ctx)->mutex) 113 #define CC_LOCK_TRYLOCK(lock_ctx) lck_mtx_try_lock((lock_ctx)->mutex) 114 #define CC_LOCK_UNLOCK(lock_ctx) lck_mtx_unlock((lock_ctx)->mutex) 115 #define CC_LOCK_ASSERT(lock_ctx) lck_mtx_assert((lock_ctx)->mutex, LCK_MTX_ASSERT_OWNED); 116 117 struct cc_lock_ctx { 118 lck_mtx_t *mutex; 119 lck_grp_t *group; 120 }; 121 122 //------------------------------------------------------------------------------ 123 // Windows 124 //------------------------------------------------------------------------------ 125 #elif CC_LOCK_IMPL_WIN 126 127 #define CC_LOCK_LOCK(lock_ctx) \ 128 if (WaitForSingleObject((lock_ctx)->hMutex, INFINITE) != WAIT_OBJECT_0) \ 129 return CCERR_INTERNAL; 130 #define CC_LOCK_UNLOCK(lock_ctx) ReleaseMutex((lock_ctx)->hMutex) 131 #define CC_LOCK_ASSERT(lock_ctx) 132 133 struct cc_lock_ctx { 134 HANDLE hMutex; 135 }; 136 137 //------------------------------------------------------------------------------ 138 // SGX 139 //------------------------------------------------------------------------------ 140 #elif CC_LOCK_IMPL_SGX 141 // Avoid an OCALL in the middle of RNG routines: use spinlocks instead of mutexes. 142 #include <pthread.h> 143 144 #define CC_LOCK_LOCK(lock_ctx) pthread_spin_lock(&(lock_ctx)->lock) 145 #define CC_LOCK_UNLOCK(lock_ctx) pthread_spin_unlock(&(lock_ctx)->lock) 146 #define CC_LOCK_ASSERT(lock_ctx) 147 148 struct cc_lock_ctx { 149 pthread_spinlock_t lock; 150 }; 151 152 //------------------------------------------------------------------------------ 153 // default 154 //------------------------------------------------------------------------------ 155 #else 156 #error "cc_lock is not implemented." 157 #endif /* CC_LOCK_IMPL_USER */ 158 159 #endif /* _CORECRYPTO_CC_LOCK_H_ */ 160