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
17typedef struct cc_lock_ctx cc_lock_ctx_t;
18int 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
96struct 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
111struct 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
126struct 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
141struct 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
157struct 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
172struct 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