xref: /xnu-8792.61.2/EXTERNAL_HEADERS/corecrypto/cc_lock.h (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
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