Skip to content

Commit f21a66b

Browse files
committed
fix multi-threaded operation
Fixes #118, #130, #134
1 parent 66a4467 commit f21a66b

29 files changed

+459
-64
lines changed

.cirrus.yml

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
task:
22
freebsd_instance:
3-
image_family: freebsd-14-0
3+
image_family: freebsd-14-2
44
env:
55
PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
66
LD_LIBRARY_PATH: /usr/local/lib
77
PATH: ${PATH}:/usr/local/sbin:/usr/sbin
8+
TPM2ABRMD_TCTI: "mssim:host=localhost,port=2321"
89
TPM2TOOLS_TCTI: "tabrmd:bus_name=com.intel.tss2.Tabrmd"
910
TPM2OPENSSL_TCTI: ${TPM2TOOLS_TCTI}
1011
IBMSWTPM_VER: rev183-2024-08-02
@@ -33,8 +34,10 @@ task:
3334
run_simulator_background_script:
3435
ibmswtpm2-$IBMSWTPM_VER/src/tpm_server
3536

36-
run_abrmd_background_script: |
37-
sudo -u _tss tpm2-abrmd --tcti mssim:host=localhost,port=2321
37+
run_abrmd_script: |
38+
sleep 1
39+
service tpm2-abrmd enable
40+
service tpm2-abrmd start
3841
3942
check_script: |
4043
openssl version

.github/workflows/clang-asan-check.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
branch: [openssl-3.0, openssl-3.1, openssl-3.2, master]
18-
runs-on: ubuntu-latest
18+
runs-on: ubuntu-22.04
1919
steps:
2020
- uses: actions/checkout@v4
2121

.github/workflows/codeql.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
jobs:
99
analyze:
1010
name: Analyze
11-
runs-on: ubuntu-latest
11+
runs-on: ubuntu-22.04
1212
permissions:
1313
actions: read
1414
contents: read
@@ -29,15 +29,15 @@ jobs:
2929
sudo apt-get install --yes autoconf-archive libtss2-dev
3030
3131
- name: Initialize CodeQL
32-
uses: github/codeql-action/init@v2
32+
uses: github/codeql-action/init@v3
3333
with:
3434
languages: ${{ matrix.language }}
3535
queries: +security-and-quality
3636

3737
- name: Autobuild
38-
uses: github/codeql-action/autobuild@v2
38+
uses: github/codeql-action/autobuild@v3
3939

4040
- name: Perform CodeQL Analysis
41-
uses: github/codeql-action/analyze@v2
41+
uses: github/codeql-action/analyze@v3
4242
with:
4343
category: "/language:${{ matrix.language }}"

.github/workflows/coverity-scan.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
jobs:
99
latest:
1010
if: github.repository == 'tpm2-software/tpm2-openssl'
11-
runs-on: ubuntu-latest
11+
runs-on: ubuntu-22.04
1212
steps:
1313
- uses: actions/checkout@v4
1414

.github/workflows/gcc-distcheck.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ env:
88

99
jobs:
1010
build:
11-
runs-on: ubuntu-latest
11+
runs-on: ubuntu-22.04
1212
steps:
1313
- uses: actions/checkout@v4
1414

@@ -51,7 +51,7 @@ jobs:
5151
TPM2OPENSSL_TCTI: ${{ env.TCTI_ADDRESS }}
5252

5353
- name: Submit code coverage
54-
uses: codecov/codecov-action@v1.2.1
54+
uses: codecov/codecov-action@v5
5555

5656
- name: Check the distribution
5757
# AM_DISTCHECK_CONFIGURE_FLAGS are not ready for clang and asan

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ test/.dirstamp
2727
test/*.o
2828
test/*.trs
2929
test/selftest
30+
test/rand_processes
31+
test/rand_threads
3032
test/ec_genpkey_store_load
3133
test/ec_genpkey_x509_csr
3234
test/rsa_genpkey_decrypt

Makefile.am

+14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ tpm2_la_SOURCES = \
77
src/tpm2-provider.c \
88
src/tpm2-provider.h \
99
src/tpm2-provider-core.c \
10+
src/tpm2-provider-semaphore.c \
11+
src/tpm2-provider-semaphore.h \
1012
src/tpm2-provider-types.c \
1113
src/tpm2-provider-types.h \
1214
src/tpm2-provider-x509.c \
@@ -58,6 +60,18 @@ test_selftest_CFLAGS = $(COMMON_CFLAGS)
5860
test_selftest_LDADD = $(CRYPTO_LIBS)
5961
test_selftest_LDFLAGS = $(COMMON_LDFLAGS)
6062

63+
check_PROGRAMS += test/rand_processes
64+
test_rand_processes_SOURCES = test/rand_processes.c
65+
test_rand_processes_CFLAGS = $(COMMON_CFLAGS)
66+
test_rand_processes_LDADD = $(CRYPTO_LIBS)
67+
test_rand_processes_LDFLAGS = $(COMMON_LDFLAGS)
68+
69+
check_PROGRAMS += test/rand_threads
70+
test_rand_threads_SOURCES = test/rand_threads.c
71+
test_rand_threads_CFLAGS = $(COMMON_CFLAGS)
72+
test_rand_threads_LDADD = $(CRYPTO_LIBS)
73+
test_rand_threads_LDFLAGS = $(COMMON_LDFLAGS)
74+
6175
check_PROGRAMS += test/ec_genpkey_store_load
6276
test_ec_genpkey_store_load_SOURCES = test/ec_genpkey_store_load.c
6377
test_ec_genpkey_store_load_CFLAGS = $(COMMON_CFLAGS)

docs/CHANGELOG.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
55

66
## [1.3.0] - 2024-xx-yy
77
### Added
8-
- Added support for RSA-OAEP decryption
9-
- Added Parent to textual information printed by 'openssl pkey -text'
8+
- Added support for RSA-OAEP decryption.
9+
- Added Parent to textual information printed by 'openssl pkey -text'.
1010
### Fixed
11+
- Fixed multi-threaded operation, preventing the 'Esys called in bad sequence'
12+
errors (thanks to @Danigaralfo, @famez, and @AndreasFuchsTPM).
1113
- Fixed handling of absent emptyAuth value in the TSS2 PRIVATE KEY file.
1214
- Set authorization value of newly generated keys. This allows users of the
1315
C API to direcly use just generated EVP_PKEY.

src/tpm2-provider-asymcipher-rsa.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ typedef struct tpm2_rsa_asymcipher_ctx_st TPM2_RSA_ASYMCIPHER_CTX;
2020

2121
struct tpm2_rsa_asymcipher_ctx_st {
2222
const OSSL_CORE_HANDLE *core;
23+
tpm2_semaphore_t esys_lock;
2324
ESYS_CONTEXT *esys_ctx;
2425
TPM2_CAPABILITY capability;
2526
TPMT_RSA_DECRYPT decrypt;
@@ -47,6 +48,7 @@ static void
4748
return NULL;
4849

4950
actx->core = cprov->core;
51+
actx->esys_lock = cprov->esys_lock;
5052
actx->esys_ctx = cprov->esys_ctx;
5153
actx->capability = cprov->capability;
5254
actx->decrypt.scheme = TPM2_ALG_RSAES;
@@ -78,9 +80,12 @@ decrypt_message(TPM2_RSA_ASYMCIPHER_CTX *actx,
7880
cipher.size = inlen;
7981
memcpy(cipher.buffer, in, inlen);
8082

83+
if (!tpm2_semaphore_lock(actx->esys_lock))
84+
return 0;
8185
r = Esys_RSA_Decrypt(actx->esys_ctx, actx->pkey->object,
8286
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
8387
&cipher, &actx->decrypt, &label, &actx->message);
88+
tpm2_semaphore_unlock(actx->esys_lock);
8489
TPM2_CHECK_RC(actx->core, r, TPM2_ERR_CANNOT_DECRYPT, return 0);
8590

8691
return 1;
@@ -114,9 +119,7 @@ rsa_asymcipher_freectx(void *ctx)
114119
if (actx == NULL)
115120
return;
116121

117-
if (actx->message != NULL)
118-
free(actx->message);
119-
122+
free(actx->message);
120123
OPENSSL_clear_free(actx, sizeof(TPM2_RSA_ASYMCIPHER_CTX));
121124
}
122125

src/tpm2-provider-cipher.c

+19-10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ typedef struct tpm2_cipher_ctx_st TPM2_CIPHER_CTX;
1414

1515
struct tpm2_cipher_ctx_st {
1616
const OSSL_CORE_HANDLE *core;
17+
tpm2_semaphore_t esys_lock;
1718
ESYS_CONTEXT *esys_ctx;
1819
TPM2_CAPABILITY capability;
1920
ESYS_TR object;
@@ -46,6 +47,7 @@ tpm2_cipher_all_newctx(void *provctx,
4647
return NULL;
4748

4849
cctx->core = cprov->core;
50+
cctx->esys_lock = cprov->esys_lock;
4951
cctx->esys_ctx = cprov->esys_ctx;
5052
cctx->capability = cprov->capability;
5153
cctx->algorithm = algdef;
@@ -82,7 +84,7 @@ tpm2_cipher_freectx(void *ctx)
8284
if (cctx == NULL)
8385
return;
8486

85-
Esys_FlushContext(cctx->esys_ctx, cctx->object);
87+
tpm2_esys_flush_context(cctx->esys_lock, cctx->esys_ctx, cctx->object);
8688
OPENSSL_clear_free(cctx->ivector, sizeof(TPM2B_IV));
8789

8890
OPENSSL_clear_free(cctx, sizeof(TPM2_CIPHER_CTX));
@@ -127,18 +129,21 @@ tpm2_load_external_key(TPM2_CIPHER_CTX *cctx, ESYS_TR parent,
127129
TPM2B_PUBLIC *keyPublic = NULL;
128130
TPM2B_PRIVATE *keyPrivate = NULL;
129131

132+
if (!tpm2_semaphore_lock(cctx->esys_lock))
133+
return 0;
130134
/* older TPM2 chips do not support Esys_CreateLoaded */
131135
r = Esys_Create(cctx->esys_ctx, parent,
132136
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
133137
&inSensitive, &inPublic, &outside_info, &creation_pcr,
134138
&keyPrivate, &keyPublic, NULL, NULL, NULL);
135-
TPM2_CHECK_RC(cctx->core, r, TPM2_ERR_CANNOT_CREATE_KEY, return 0);
136-
137-
r = Esys_Load(cctx->esys_ctx, parent,
138-
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
139-
keyPrivate, keyPublic, &cctx->object);
140-
free(keyPublic);
141-
free(keyPrivate);
139+
if (!r) {
140+
r = Esys_Load(cctx->esys_ctx, parent,
141+
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
142+
keyPrivate, keyPublic, &cctx->object);
143+
free(keyPublic);
144+
free(keyPrivate);
145+
}
146+
tpm2_semaphore_unlock(cctx->esys_lock);
142147
TPM2_CHECK_RC(cctx->core, r, TPM2_ERR_CANNOT_CREATE_KEY, return 0);
143148

144149
return 1;
@@ -158,12 +163,13 @@ tpm2_cipher_init(TPM2_CIPHER_CTX *cctx,
158163
DBG("CIPHER %sCRYPT_INIT load key %zu bytes\n",
159164
cctx->decrypt ? "DE" : "EN", keylen);
160165

161-
if (!tpm2_build_primary(cctx->core, cctx->esys_ctx, cctx->capability.algorithms,
166+
if (!tpm2_build_primary(cctx->core, cctx->esys_lock, cctx->esys_ctx,
167+
cctx->capability.algorithms,
162168
ESYS_TR_RH_NULL, NULL, &parent))
163169
return 0;
164170

165171
res = tpm2_load_external_key(cctx, parent, key, keylen);
166-
Esys_FlushContext(cctx->esys_ctx, parent);
172+
tpm2_esys_flush_context(cctx->esys_lock, cctx->esys_ctx, parent);
167173
if (!res)
168174
return 0;
169175
}
@@ -212,6 +218,8 @@ encrypt_decrypt(TPM2_CIPHER_CTX *cctx,
212218
{
213219
TSS2_RC r;
214220

221+
if (!tpm2_semaphore_lock(cctx->esys_lock))
222+
return 0;
215223
r = Esys_EncryptDecrypt2(cctx->esys_ctx, cctx->object,
216224
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
217225
&cctx->buffer, cctx->decrypt, TPM2_ALG_NULL,
@@ -222,6 +230,7 @@ encrypt_decrypt(TPM2_CIPHER_CTX *cctx,
222230
cctx->decrypt, TPM2_ALG_NULL, cctx->ivector,
223231
&cctx->buffer, outbuff, ivector);
224232
}
233+
tpm2_semaphore_unlock(cctx->esys_lock);
225234

226235
return r;
227236
}

src/tpm2-provider-core.c

+28
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,34 @@ tpm2_list_params(const char *text, const OSSL_PARAM params[])
100100
fprintf(stderr, " ]\n");
101101
}
102102

103+
TSS2_RC
104+
tpm2_esys_tr_close(tpm2_semaphore_t esys_lock, ESYS_CONTEXT *esys_ctx, ESYS_TR *object)
105+
{
106+
TSS2_RC r;
107+
108+
if (!tpm2_semaphore_lock(esys_lock))
109+
return TSS2_ESYS_RC_GENERAL_FAILURE;
110+
111+
r = Esys_TR_Close(esys_ctx, object);
112+
113+
tpm2_semaphore_unlock(esys_lock);
114+
return r;
115+
}
116+
117+
TSS2_RC
118+
tpm2_esys_flush_context(tpm2_semaphore_t esys_lock, ESYS_CONTEXT *esys_ctx, ESYS_TR flush_handle)
119+
{
120+
TSS2_RC r;
121+
122+
if (!tpm2_semaphore_lock(esys_lock))
123+
return TSS2_ESYS_RC_GENERAL_FAILURE;
124+
125+
r = Esys_FlushContext(esys_ctx, flush_handle);
126+
127+
tpm2_semaphore_unlock(esys_lock);
128+
return r;
129+
}
130+
103131
int
104132
tpm2_supports_algorithm(const TPMS_CAPABILITY_DATA *caps, TPM2_ALG_ID algorithm)
105133
{

src/tpm2-provider-decoder-tss2.c

+19-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ typedef struct tpm2_tss2_decoder_ctx_st TPM2_TSS2_DECODER_CTX;
2020
struct tpm2_tss2_decoder_ctx_st {
2121
const OSSL_CORE_HANDLE *core;
2222
OSSL_LIB_CTX *libctx;
23+
tpm2_semaphore_t esys_lock;
2324
ESYS_CONTEXT *esys_ctx;
2425
TPM2_CAPABILITY capability;
2526
TPM2B_DIGEST parentAuth;
@@ -42,6 +43,7 @@ tpm2_tss2_decoder_newctx(void *provctx)
4243

4344
dctx->core = cprov->core;
4445
dctx->libctx = cprov->libctx;
46+
dctx->esys_lock = cprov->esys_lock;
4547
dctx->esys_ctx = cprov->esys_ctx;
4648
dctx->capability = cprov->capability;
4749
return dctx;
@@ -70,16 +72,19 @@ decode_privkey(TPM2_TSS2_DECODER_CTX *dctx, TPM2_PKEY *pkey,
7072

7173
if (pkey->data.parent && pkey->data.parent != TPM2_RH_OWNER) {
7274
DBG("TSS2 DECODER LOAD parent: persistent 0x%x\n", pkey->data.parent);
73-
if (!tpm2_load_parent(pkey->core, pkey->esys_ctx,
75+
if (!tpm2_load_parent(pkey->core, pkey->esys_lock, pkey->esys_ctx,
7476
pkey->data.parent, &dctx->parentAuth, &parent))
7577
goto error1;
7678
} else {
7779
DBG("TSS2 DECODER LOAD parent: primary 0x%x\n", TPM2_RH_OWNER);
78-
if (!tpm2_build_primary(pkey->core, pkey->esys_ctx, pkey->capability.algorithms,
80+
if (!tpm2_build_primary(pkey->core, pkey->esys_lock, pkey->esys_ctx,
81+
pkey->capability.algorithms,
7982
ESYS_TR_RH_OWNER, &dctx->parentAuth, &parent))
8083
goto error1;
8184
}
8285

86+
if (!tpm2_semaphore_lock(pkey->esys_lock))
87+
goto error1;
8388
r = Esys_Load(pkey->esys_ctx, parent,
8489
ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
8590
&pkey->data.priv, &pkey->data.pub, &pkey->object);
@@ -89,11 +94,15 @@ decode_privkey(TPM2_TSS2_DECODER_CTX *dctx, TPM2_PKEY *pkey,
8994
else
9095
Esys_FlushContext(pkey->esys_ctx, parent);
9196

97+
tpm2_semaphore_unlock(pkey->esys_lock);
9298
TPM2_CHECK_RC(pkey->core, r, TPM2_ERR_CANNOT_LOAD_KEY, goto error1);
9399
} else if (pkey->data.privatetype == KEY_TYPE_HANDLE) {
100+
if (!tpm2_semaphore_lock(pkey->esys_lock))
101+
goto error1;
94102
r = Esys_TR_FromTPMPublic(pkey->esys_ctx, pkey->data.handle,
95103
ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
96104
&pkey->object);
105+
tpm2_semaphore_unlock(pkey->esys_lock);
97106
TPM2_CHECK_RC(pkey->core, r, TPM2_ERR_CANNOT_LOAD_KEY, goto error1);
98107
} else {
99108
TPM2_ERROR_raise(pkey->core, TPM2_ERR_INPUT_CORRUPTED);
@@ -111,7 +120,10 @@ decode_privkey(TPM2_TSS2_DECODER_CTX *dctx, TPM2_PKEY *pkey,
111120
}
112121
userauth.size = plen;
113122

123+
if (!tpm2_semaphore_lock(pkey->esys_lock))
124+
goto error2;
114125
r = Esys_TR_SetAuth(dctx->esys_ctx, pkey->object, &userauth);
126+
tpm2_semaphore_unlock(pkey->esys_lock);
115127
TPM2_CHECK_RC(dctx->core, r, TPM2_ERR_CANNOT_LOAD_KEY, goto error2);
116128
}
117129

@@ -123,9 +135,9 @@ decode_privkey(TPM2_TSS2_DECODER_CTX *dctx, TPM2_PKEY *pkey,
123135
return keytype;
124136
error2:
125137
if (pkey->data.privatetype == KEY_TYPE_HANDLE)
126-
Esys_TR_Close(pkey->esys_ctx, &pkey->object);
138+
tpm2_esys_tr_close(pkey->esys_lock, pkey->esys_ctx, &pkey->object);
127139
else
128-
Esys_FlushContext(pkey->esys_ctx, pkey->object);
140+
tpm2_esys_flush_context(pkey->esys_lock, pkey->esys_ctx, pkey->object);
129141
error1:
130142
pkey->object = ESYS_TR_NONE;
131143
return NULL;
@@ -156,6 +168,7 @@ tpm2_tss2_decoder_decode(void *ctx, OSSL_CORE_BIO *cin, int selection,
156168
goto error2;
157169

158170
pkey->core = dctx->core;
171+
pkey->esys_lock = dctx->esys_lock;
159172
pkey->esys_ctx = dctx->esys_ctx;
160173
pkey->capability = dctx->capability;
161174
pkey->object = ESYS_TR_NONE;
@@ -188,9 +201,9 @@ tpm2_tss2_decoder_decode(void *ctx, OSSL_CORE_BIO *cin, int selection,
188201
error1:
189202
if (pkey->object != ESYS_TR_NONE) {
190203
if (pkey->data.privatetype == KEY_TYPE_HANDLE)
191-
Esys_TR_Close(pkey->esys_ctx, &pkey->object);
204+
tpm2_esys_tr_close(pkey->esys_lock, pkey->esys_ctx, &pkey->object);
192205
else
193-
Esys_FlushContext(pkey->esys_ctx, pkey->object);
206+
tpm2_esys_flush_context(pkey->esys_lock, pkey->esys_ctx, pkey->object);
194207
}
195208
OPENSSL_clear_free(pkey, sizeof(TPM2_PKEY));
196209
return res;

0 commit comments

Comments
 (0)