Skip to content

Commit d4cab69

Browse files
committed
Return new error CTX_BUSY_E on APIs which would modify aliased buffers
1 parent 5d0da8e commit d4cab69

9 files changed

Lines changed: 293 additions & 24 deletions

File tree

doc/dox_comments/header_files/ssl.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,8 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl,
10271027
given using the “format” argument, file doesn’t exist, can’t be read,
10281028
or is corrupted, an out of memory condition occurs, Base16 decoding
10291029
fails on the file.
1030+
\return CTX_BUSY_E if any WOLFSSL session created from this context is
1031+
still active; see the note below.
10301032

10311033
\param ctx a pointer to a WOLFSSL_CTX structure, created using
10321034
wolfSSL_CTX_new()
@@ -1048,9 +1050,17 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl,
10481050
...
10491051
\endcode
10501052

1053+
\note The context certificate is shared with every WOLFSSL session created
1054+
from it, so this function refuses to change it while any such session is
1055+
active and returns CTX_BUSY_E. Load the certificate before creating
1056+
sessions. To set a certificate for one connection, call
1057+
wolfSSL_use_certificate_file() on the WOLFSSL object, or switch the session
1058+
to a preconfigured context with wolfSSL_set_SSL_CTX().
1059+
10511060
\sa wolfSSL_CTX_use_certificate_buffer
10521061
\sa wolfSSL_use_certificate_file
10531062
\sa wolfSSL_use_certificate_buffer
1063+
\sa wolfSSL_set_SSL_CTX
10541064
*/
10551065
int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
10561066
int format);
@@ -1077,6 +1087,8 @@ int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
10771087
be read, or is corrupted. An out of memory condition occurs. Base16
10781088
decoding fails on the file. The key file is encrypted but no password
10791089
is provided.
1090+
\return CTX_BUSY_E if any WOLFSSL session created from this context is
1091+
still active; see the note below.
10801092

10811093
\param ctx pointer to a WOLFSSL_CTX structure.
10821094
\param file path to the private key file.
@@ -1096,11 +1108,19 @@ int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
10961108
...
10971109
\endcode
10981110

1111+
\note The context private key is shared with every WOLFSSL session created
1112+
from it (the server signs with it), so this function refuses to change it
1113+
while any such session is active and returns CTX_BUSY_E. Load the key
1114+
before creating sessions. To set a key for one connection, call
1115+
wolfSSL_use_PrivateKey_file() on the WOLFSSL object, or switch the session
1116+
to a preconfigured context with wolfSSL_set_SSL_CTX().
1117+
10991118
\sa wolfSSL_CTX_use_PrivateKey_buffer
11001119
\sa wolfSSL_use_PrivateKey_file
11011120
\sa wolfSSL_use_PrivateKey_buffer
11021121
\sa wc_CryptoCb_RegisterDevice
11031122
\sa wolfSSL_CTX_SetDevId
1123+
\sa wolfSSL_set_SSL_CTX
11041124
*/
11051125
int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, int format);
11061126

@@ -1543,9 +1563,15 @@ long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx);
15431563
...
15441564
\endcode
15451565

1566+
\note This updates the WOLFSSL session's own buffers and does not touch the
1567+
shared WOLFSSL_CTX, so unlike wolfSSL_CTX_use_certificate_file() it is safe
1568+
to call while other sessions are active, including from the SNI (server
1569+
name) callback to set a certificate for the current connection.
1570+
15461571
\sa wolfSSL_CTX_use_certificate_buffer
15471572
\sa wolfSSL_CTX_use_certificate_file
15481573
\sa wolfSSL_use_certificate_buffer
1574+
\sa wolfSSL_set_SSL_CTX
15491575
*/
15501576
int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format);
15511577

@@ -1591,11 +1617,17 @@ int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format);
15911617
...
15921618
\endcode
15931619

1620+
\note This updates the WOLFSSL session's own buffers and does not touch the
1621+
shared WOLFSSL_CTX, so unlike wolfSSL_CTX_use_PrivateKey_file() it is safe
1622+
to call while other sessions are active, including from the SNI (server
1623+
name) callback to set a private key for the current connection.
1624+
15941625
\sa wolfSSL_CTX_use_PrivateKey_buffer
15951626
\sa wolfSSL_CTX_use_PrivateKey_file
15961627
\sa wolfSSL_use_PrivateKey_buffer
15971628
\sa wc_CryptoCb_RegisterDevice
15981629
\sa wolfSSL_SetDevId
1630+
\sa wolfSSL_set_SSL_CTX
15991631
*/
16001632
int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format);
16011633

@@ -7707,6 +7739,9 @@ int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* f, int format);
77077739
than the value of the maxDhKeySz member of the WOLFSSL_CTX struct.
77087740
\return MEMORY_E returned if the allocation of memory failed in this
77097741
function or a subroutine.
7742+
\return CTX_BUSY_E returned if any WOLFSSL session created from this context
7743+
is still active; the shared DH parameters cannot be changed then. Set them
7744+
before creating sessions, or use wolfSSL_SetTmpDH() on the WOLFSSL object.
77107745

77117746
\param ctx a pointer to a WOLFSSL_CTX structure, created using
77127747
wolfSSL_CTX_new().
@@ -8237,7 +8272,8 @@ int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx);
82378272
\return SSL_SUCCESS returned on successful execution of the function.
82388273
\return BAD_FUNC_ARG returned if the WOLFSSL_CTX struct is NULL or there
82398274
are otherwise unpermitted argument values passed in a subroutine.
8240-
\return BAD_STATE_E returned if the WOLFSSL_CTX has a reference count > 1.
8275+
\return CTX_BUSY_E returned if the WOLFSSL_CTX has a reference count > 1
8276+
(active sessions exist).
82418277
\return BAD_MUTEX_E returned if there was a mutex error. The LockMutex()
82428278
did not return 0.
82438279

src/internal.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29047,6 +29047,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
2904729047

2904829048
case RPK_UNTRUSTED_E:
2904929049
return "RFC 7250 Raw Public Key not trusted";
29050+
29051+
case CTX_BUSY_E:
29052+
return "Context in use by active sessions, operation not allowed";
2905029053
}
2905129054

2905229055
return "unknown error number";

src/ssl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12830,6 +12830,10 @@ long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt)
1283012830
ret = WOLFSSL_FAILURE;
1283112831
break;
1283212832
}
12833+
if (wolfssl_ctx_resources_in_use(ctx)) {
12834+
ret = CTX_BUSY_E;
12835+
break;
12836+
}
1283312837
/* Clear certificate chain */
1283412838
FreeDer(&ctx->certChain);
1283512839
if (sk) {

src/ssl_api_cert.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1065,7 +1065,7 @@ int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx)
10651065
if (ctx->ref.count > 1) {
10661066
WOLFSSL_MSG("ctx object must have a ref count of 1 before "
10671067
"unloading intermediate certs");
1068-
ret = BAD_STATE_E;
1068+
ret = CTX_BUSY_E;
10691069
}
10701070
else {
10711071
ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm);

src/ssl_load.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,6 +2377,35 @@ static int ProcessBufferResetSuites(WOLFSSL_CTX* ctx, WOLFSSL* ssl, int type)
23772377
((type) == ALT_PRIVATEKEY_TYPE))
23782378
#endif
23792379

2380+
/* Whether other objects still reference this context's shared buffers.
2381+
*
2382+
* Every WOLFSSL created from a context aliases the context's certificate, key
2383+
* and DH buffers and holds a reference on the context. A reference count above
2384+
* one therefore means such aliases exist, so those buffers must not be freed
2385+
* or replaced.
2386+
*
2387+
* @param [in] ctx SSL context object.
2388+
* @return 1 when the context is in use by other objects.
2389+
* @return 0 otherwise.
2390+
*/
2391+
static int wolfssl_ctx_resources_in_use(WOLFSSL_CTX* ctx)
2392+
{
2393+
int inUse = 0;
2394+
2395+
if (ctx != NULL) {
2396+
/* Block when the count can't be read so we never free a live alias. */
2397+
if (wolfSSL_RefWithMutexLock(&ctx->ref) != 0) {
2398+
inUse = 1;
2399+
}
2400+
else {
2401+
inUse = (ctx->ref.count > 1);
2402+
(void)wolfSSL_RefWithMutexUnlock(&ctx->ref);
2403+
}
2404+
}
2405+
2406+
return inUse;
2407+
}
2408+
23802409
/* Process a buffer of data.
23812410
*
23822411
* Data type is a private key or a certificate.
@@ -2435,6 +2464,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz,
24352464
if ((ret == 0) && (sz < 0)) {
24362465
ret = BAD_FUNC_ARG;
24372466
}
2467+
if ((ret == 0) && (ssl == NULL) &&
2468+
((type == CERT_TYPE) || IS_PRIVKEY_TYPE(type)) &&
2469+
wolfssl_ctx_resources_in_use(ctx)) {
2470+
ret = CTX_BUSY_E;
2471+
}
24382472

24392473
#ifdef WOLFSSL_SMALL_STACK
24402474
if (ret == 0) {
@@ -3206,6 +3240,10 @@ int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
32063240

32073241
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
32083242

3243+
if (wolfssl_ctx_resources_in_use(ctx)) {
3244+
return CTX_BUSY_E;
3245+
}
3246+
32093247
ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
32103248
GET_VERIFY_SETTING_CTX(ctx));
32113249

@@ -3231,6 +3269,10 @@ int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
32313269

32323270
WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
32333271

3272+
if (wolfssl_ctx_resources_in_use(ctx)) {
3273+
return CTX_BUSY_E;
3274+
}
3275+
32343276
ret = ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
32353277
GET_VERIFY_SETTING_CTX(ctx));
32363278

@@ -3255,6 +3297,10 @@ int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
32553297

32563298
WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file");
32573299

3300+
if (wolfssl_ctx_resources_in_use(ctx)) {
3301+
return CTX_BUSY_E;
3302+
}
3303+
32583304
ret = ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL,
32593305
GET_VERIFY_SETTING_CTX(ctx));
32603306

@@ -3279,6 +3325,10 @@ int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
32793325
/* process up to MAX_CHAIN_DEPTH plus subject cert */
32803326
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
32813327

3328+
if (wolfssl_ctx_resources_in_use(ctx)) {
3329+
return CTX_BUSY_E;
3330+
}
3331+
32823332
#ifdef WOLFSSL_PEM_TO_DER
32833333
ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
32843334
GET_VERIFY_SETTING_CTX(ctx));
@@ -3309,6 +3359,10 @@ int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
33093359

33103360
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
33113361

3362+
if (wolfssl_ctx_resources_in_use(ctx)) {
3363+
return CTX_BUSY_E;
3364+
}
3365+
33123366
ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
33133367
GET_VERIFY_SETTING_CTX(ctx));
33143368

@@ -4211,6 +4265,9 @@ int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
42114265
if (ctx == NULL || id == NULL || sz < 0) {
42124266
return 0;
42134267
}
4268+
if (wolfssl_ctx_resources_in_use(ctx)) {
4269+
return CTX_BUSY_E;
4270+
}
42144271

42154272
/* Dispose of old private key and allocate and copy in id. */
42164273
FreeDer(&ctx->privateKey);
@@ -4287,6 +4344,9 @@ int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
42874344
if (ctx == NULL || label == NULL) {
42884345
return 0;
42894346
}
4347+
if (wolfssl_ctx_resources_in_use(ctx)) {
4348+
return CTX_BUSY_E;
4349+
}
42904350

42914351
sz = (word32)XSTRLEN(label) + 1;
42924352

@@ -4330,6 +4390,9 @@ int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
43304390
if ((ctx == NULL) || (id == NULL) || (sz < 0)) {
43314391
ret = 0;
43324392
}
4393+
if ((ret == 1) && wolfssl_ctx_resources_in_use(ctx)) {
4394+
ret = CTX_BUSY_E;
4395+
}
43334396

43344397
if (ret == 1) {
43354398
FreeDer(&ctx->altPrivateKey);
@@ -4380,6 +4443,9 @@ int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
43804443
if ((ctx == NULL) || (label == NULL)) {
43814444
ret = 0;
43824445
}
4446+
if ((ret == 1) && wolfssl_ctx_resources_in_use(ctx)) {
4447+
ret = CTX_BUSY_E;
4448+
}
43834449

43844450
if (ret == 1) {
43854451
sz = (word32)XSTRLEN(label) + 1;
@@ -4954,6 +5020,10 @@ static int wolfssl_ctx_add_to_chain(WOLFSSL_CTX* ctx, const byte* der,
49545020
int ret;
49555021
DerBuffer* derBuffer = NULL;
49565022

5023+
if (wolfssl_ctx_resources_in_use(ctx)) {
5024+
return CTX_BUSY_E;
5025+
}
5026+
49575027
/* Create a DER buffer from DER encoding. */
49585028
ret = AllocCopyDer(&derBuffer, der, (word32)derSz, CERT_TYPE, ctx->heap);
49595029
if (ret != 0) {
@@ -5063,6 +5133,9 @@ int wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
50635133
WOLFSSL_MSG("Bad parameter");
50645134
res = 0;
50655135
}
5136+
if ((res == 1) && wolfssl_ctx_resources_in_use(ctx)) {
5137+
res = CTX_BUSY_E;
5138+
}
50665139

50675140
if (res == 1) {
50685141
/* Replace certificate buffer with one holding the new certificate. */
@@ -5305,6 +5378,9 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
53055378
if ((ctx == NULL) || (pkey == NULL) || (pkey->pkey.ptr == NULL)) {
53065379
ret = 0;
53075380
}
5381+
if ((ret == 1) && wolfssl_ctx_resources_in_use(ctx)) {
5382+
ret = CTX_BUSY_E;
5383+
}
53085384

53095385
if (ret == 1) {
53105386
switch (pkey->type) {
@@ -5376,6 +5452,9 @@ int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz,
53765452
if ((ctx == NULL) || (der == NULL)) {
53775453
ret = 0;
53785454
}
5455+
if ((ret == 1) && wolfssl_ctx_resources_in_use(ctx)) {
5456+
ret = CTX_BUSY_E;
5457+
}
53795458
/* Load DER encoded certificate into SSL context. */
53805459
if ((ret == 1) && (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz,
53815460
WOLFSSL_FILETYPE_ASN1) != 1)) {
@@ -5409,6 +5488,9 @@ int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
54095488
WOLFSSL_MSG("one or more inputs were NULL");
54105489
ret = BAD_FUNC_ARG;
54115490
}
5491+
if ((ret == 1) && wolfssl_ctx_resources_in_use(ctx)) {
5492+
ret = CTX_BUSY_E;
5493+
}
54125494

54135495
/* Get DER encoding size. */
54145496
if ((ret == 1) && ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, NULL)) <= 0)) {
@@ -5752,6 +5834,10 @@ static int wolfssl_ctx_set_tmp_dh(WOLFSSL_CTX* ctx, unsigned char* p, int pSz,
57525834
if ((ctx == NULL) || (p == NULL) || (g == NULL))
57535835
ret = BAD_FUNC_ARG;
57545836

5837+
if ((ret == 1) && wolfssl_ctx_resources_in_use(ctx)) {
5838+
ret = CTX_BUSY_E;
5839+
}
5840+
57555841
/* Check the size of the prime meets the requirements of the SSL context. */
57565842
if (ret == 1) {
57575843
if (((word16)pSz < ctx->minDhKeySz) || ((word16)pSz > ctx->maxDhKeySz)) {

0 commit comments

Comments
 (0)