Skip to content

Commit 4a36d16

Browse files
committed
Fix bugs found in crl.c, keys.c, and ssl_certman.c review
crl.c: - wolfSSL_X509_CRL_dup: add NULL check on input before dereferencing crl->cm - DupX509_CRL: distinguish empty source CRL list from allocation failure so duplicating a CRL with no entries no longer returns MEMORY_E - wolfSSL_X509_STORE_add_crl: free newly-allocated CRL when wc_LockRwLock_Rd fails to avoid leaking it - InitCRL: propagate wolfSSL_RefInit failure in OPENSSL_ALL + WOLFSSL_REFCNT_ERROR_RETURN builds, freeing crlLock (and cond when HAVE_CRL_MONITOR is enabled) on the error path keys.c: - GetCipherSpec: remove duplicate usingPSK_cipher assignment in BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 case - GetCipherSpec: return UNSUPPORTED_SUITE for unknown cipher suite bytes in the TLS13_BYTE, ECDHE_PSK_BYTE, and SM_BYTE switch blocks, matching the behavior of the ECC_BYTE, CHACHA_BYTE, and normal suite switches - SetKeys: fix misleading indentation on the AESCCM and SM4-CCM dec->aes NULL-check return statements ssl_certman.c / internal.h: - AddTrustedPeer: remove dead code that checked peerCert->permittedNames and peerCert->excludedNames immediately after XMEMSET zeroed the struct - AddTrustedPeer: use cm->heap (matching allocation) instead of NULL when freeing cert on the ParseCert failure path - Extract the body of wolfSSL_CertManagerFree into a new static helper DoCertManagerFree that unconditionally disposes of the certificate manager, bypassing the reference count check. wolfSSL_CertManagerFree now delegates to it after the RefDec check. - Add caLockInit, tpLockInit, and refInit bitfield members to WOLFSSL_CERT_MANAGER that track which sub-resources were successfully initialized. DoCertManagerFree consults these flags so that it only destroys mutexes and the reference count that were actually set up, which makes partial-construction cleanup safe without relying on platform-specific behavior of free-on-zeroed-storage. - wolfSSL_CertManagerNew_ex: set the init flags as each sub-resource is initialized, and on failure call DoCertManagerFree directly to free exactly the resources that succeeded. Set cm->heap immediately after XMEMSET so the forceful free path can use it.
1 parent 9176185 commit 4a36d16

4 files changed

Lines changed: 115 additions & 64 deletions

File tree

src/crl.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,18 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
9393
{
9494
int ret;
9595
wolfSSL_RefInit(&crl->ref, &ret);
96+
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
97+
if (ret != 0) {
98+
WOLFSSL_MSG("wolfSSL_RefInit failed");
99+
wc_FreeRwLock(&crl->crlLock);
100+
#ifdef HAVE_CRL_MONITOR
101+
wolfSSL_CondFree(&crl->cond);
102+
#endif
103+
return ret;
104+
}
105+
#else
96106
(void)ret;
107+
#endif
97108
}
98109
#endif
99110
#if defined(OPENSSL_EXTRA)
@@ -1451,7 +1462,7 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
14511462
#endif
14521463

14531464
dupl->crlList = DupCRL_list(crl->crlList, dupl->heap);
1454-
if (dupl->crlList == NULL)
1465+
if (crl->crlList != NULL && dupl->crlList == NULL)
14551466
return MEMORY_E;
14561467
#ifdef HAVE_CRL_IO
14571468
dupl->crlIOCb = crl->crlIOCb;
@@ -1466,6 +1477,9 @@ WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl)
14661477

14671478
WOLFSSL_ENTER("wolfSSL_X509_CRL_dup");
14681479

1480+
if (crl == NULL)
1481+
return NULL;
1482+
14691483
ret = wolfSSL_X509_crl_new(crl->cm);
14701484
if (ret != NULL && DupX509_CRL(ret, crl) != 0) {
14711485
FreeCRL(ret, 1);
@@ -1514,6 +1528,7 @@ int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newc
15141528
}
15151529
if (wc_LockRwLock_Rd(&newcrl->crlLock) != 0) {
15161530
WOLFSSL_MSG("wc_LockRwLock_Rd failed");
1531+
FreeCRL(crl, 1);
15171532
return BAD_MUTEX_E;
15181533
}
15191534
ret = DupX509_CRL(crl, newcrl);

src/keys.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,6 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
525525
specs->block_size = WC_AES_BLOCK_SIZE;
526526
specs->iv_size = AES_IV_SIZE;
527527

528-
if (opts != NULL)
529-
opts->usingPSK_cipher = 1;
530528
if (opts != NULL)
531529
opts->usingPSK_cipher = 1;
532530
break;
@@ -1374,7 +1372,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
13741372
#endif
13751373
#endif /* WOLFSSL_TLS13 */
13761374
default:
1377-
break;
1375+
WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs TLS 1.3");
1376+
return UNSUPPORTED_SUITE;
13781377
}
13791378
}
13801379

@@ -1405,7 +1404,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
14051404
#endif
14061405

14071406
default:
1408-
break;
1407+
WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ECDHE_PSK");
1408+
return UNSUPPORTED_SUITE;
14091409
}
14101410
}
14111411

@@ -1466,7 +1466,8 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
14661466
#endif
14671467

14681468
default:
1469-
break;
1469+
WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs SM");
1470+
return UNSUPPORTED_SUITE;
14701471
}
14711472
}
14721473

@@ -2799,7 +2800,7 @@ int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
27992800
if (dec->aes == NULL) {
28002801
dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER);
28012802
if (dec->aes == NULL)
2802-
return MEMORY_E;
2803+
return MEMORY_E;
28032804
} else {
28042805
wc_AesFree(dec->aes);
28052806
}
@@ -3247,7 +3248,7 @@ int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
32473248
dec->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
32483249
DYNAMIC_TYPE_CIPHER);
32493250
if (dec->sm4 == NULL)
3250-
return MEMORY_E;
3251+
return MEMORY_E;
32513252
} else {
32523253
wc_Sm4Free(dec->sm4);
32533254
}

src/ssl_certman.c

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void* heap)
7474
#endif
7575
}
7676

77+
static void DoCertManagerFree(WOLFSSL_CERT_MANAGER* cm);
78+
7779
/* Create a new certificate manager with a heap hint.
7880
*
7981
* @param [in] heap Heap hint.
@@ -107,12 +109,17 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
107109
if (!err) {
108110
/* Reset all fields. */
109111
XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
112+
/* Set heap hint early so cleanup can use it. */
113+
cm->heap = heap;
110114

111115
/* Create a mutex for use when modify table of stored CAs. */
112116
if (wc_InitMutex(&cm->caLock) != 0) {
113117
WOLFSSL_MSG("Bad mutex init");
114118
err = 1;
115119
}
120+
else {
121+
cm->caLockInit = 1;
122+
}
116123
}
117124
if (!err) {
118125
/* Initialize reference count. */
@@ -121,13 +128,23 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
121128
if (err != 0) {
122129
WOLFSSL_MSG("Bad reference count init");
123130
}
131+
else {
132+
cm->refInit = 1;
133+
}
134+
#else
135+
cm->refInit = 1;
124136
#endif
125137
}
126138
#ifdef WOLFSSL_TRUST_PEER_CERT
127-
/* Create a mutex for use when modify table of trusted peers. */
128-
if ((!err) && (wc_InitMutex(&cm->tpLock) != 0)) {
129-
WOLFSSL_MSG("Bad mutex init");
130-
err = 1;
139+
if (!err) {
140+
/* Create a mutex for use when modify table of trusted peers. */
141+
if (wc_InitMutex(&cm->tpLock) != 0) {
142+
WOLFSSL_MSG("Bad mutex init");
143+
err = 1;
144+
}
145+
else {
146+
cm->tpLockInit = 1;
147+
}
131148
}
132149
#endif
133150
if (!err) {
@@ -144,14 +161,12 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
144161
#ifdef HAVE_DILITHIUM
145162
cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
146163
#endif /* HAVE_DILITHIUM */
147-
148-
/* Set heap hint to use in certificate manager operations. */
149-
cm->heap = heap;
150164
}
151165

152-
/* Dispose of certificate manager on error. */
166+
/* Dispose of certificate manager on error. The reference count may not
167+
* have been initialized, so bypass the ref check and free directly. */
153168
if (err && (cm != NULL)) {
154-
wolfSSL_CertManagerFree(cm);
169+
DoCertManagerFree(cm);
155170
cm = NULL;
156171
}
157172
return cm;
@@ -168,6 +183,63 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
168183
return wolfSSL_CertManagerNew_ex(NULL);
169184
}
170185

186+
/* Unconditionally dispose of all resources owned by the certificate manager
187+
* and free cm itself, bypassing any reference count check. Only frees the
188+
* sub-resources that are marked as initialized in the cm bitfield, so it is
189+
* safe to call on a cm that was only partially initialized by
190+
* wolfSSL_CertManagerNew_ex.
191+
*
192+
* @param [in, out] cm Certificate manager (must be non-NULL).
193+
*/
194+
static void DoCertManagerFree(WOLFSSL_CERT_MANAGER* cm)
195+
{
196+
#ifdef HAVE_CRL
197+
/* Dispose of CRL handler. */
198+
if (cm->crl != NULL) {
199+
/* Dispose of CRL object - indicating dynamically allocated. */
200+
FreeCRL(cm->crl, 1);
201+
}
202+
#endif
203+
204+
#ifdef HAVE_OCSP
205+
/* Dispose of OCSP handler. */
206+
if (cm->ocsp != NULL) {
207+
FreeOCSP(cm->ocsp, 1);
208+
}
209+
/* Dispose of URL. */
210+
XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
211+
#if !defined(NO_WOLFSSL_SERVER) && \
212+
(defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
213+
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
214+
/* Dispose of OCSP stapling handler. */
215+
if (cm->ocsp_stapling) {
216+
FreeOCSP(cm->ocsp_stapling, 1);
217+
}
218+
#endif
219+
#endif /* HAVE_OCSP */
220+
221+
/* Dispose of CA table and mutex. */
222+
FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
223+
if (cm->caLockInit) {
224+
wc_FreeMutex(&cm->caLock);
225+
}
226+
227+
#ifdef WOLFSSL_TRUST_PEER_CERT
228+
/* Dispose of trusted peer table and mutex. */
229+
FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
230+
if (cm->tpLockInit) {
231+
wc_FreeMutex(&cm->tpLock);
232+
}
233+
#endif
234+
235+
/* Dispose of reference count. */
236+
if (cm->refInit) {
237+
wolfSSL_RefFree(&cm->ref);
238+
}
239+
/* Dispose of certificate manager memory. */
240+
XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
241+
}
242+
171243
/* Dispose of certificate manager.
172244
*
173245
* @param [in, out] cm Certificate manager.
@@ -191,45 +263,7 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
191263
(void)ret;
192264
#endif
193265
if (doFree) {
194-
#ifdef HAVE_CRL
195-
/* Dispose of CRL handler. */
196-
if (cm->crl != NULL) {
197-
/* Dispose of CRL object - indicating dynamically allocated. */
198-
FreeCRL(cm->crl, 1);
199-
}
200-
#endif
201-
202-
#ifdef HAVE_OCSP
203-
/* Dispose of OCSP handler. */
204-
if (cm->ocsp != NULL) {
205-
FreeOCSP(cm->ocsp, 1);
206-
}
207-
/* Dispose of URL. */
208-
XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
209-
#if !defined(NO_WOLFSSL_SERVER) && \
210-
(defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
211-
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
212-
/* Dispose of OCSP stapling handler. */
213-
if (cm->ocsp_stapling) {
214-
FreeOCSP(cm->ocsp_stapling, 1);
215-
}
216-
#endif
217-
#endif /* HAVE_OCSP */
218-
219-
/* Dispose of CA table and mutex. */
220-
FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
221-
wc_FreeMutex(&cm->caLock);
222-
223-
#ifdef WOLFSSL_TRUST_PEER_CERT
224-
/* Dispose of trusted peer table and mutex. */
225-
FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
226-
wc_FreeMutex(&cm->tpLock);
227-
#endif
228-
229-
/* Dispose of reference count. */
230-
wolfSSL_RefFree(&cm->ref);
231-
/* Dispose of certificate manager memory. */
232-
XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
266+
DoCertManagerFree(cm);
233267
}
234268
}
235269
}
@@ -2859,7 +2893,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
28592893
InitDecodedCert(cert, der->buffer, der->length, cm->heap);
28602894
if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
28612895
FreeDecodedCert(cert);
2862-
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
2896+
XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
28632897
FreeDer(&der);
28642898
return ret;
28652899
}
@@ -2875,13 +2909,6 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
28752909
}
28762910
XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
28772911

2878-
#ifndef IGNORE_NAME_CONSTRAINTS
2879-
if (peerCert->permittedNames)
2880-
FreeNameSubtrees(peerCert->permittedNames, cm->heap);
2881-
if (peerCert->excludedNames)
2882-
FreeNameSubtrees(peerCert->excludedNames, cm->heap);
2883-
#endif
2884-
28852912
if (AlreadyTrustedPeer(cm, cert)) {
28862913
WOLFSSL_MSG("\tAlready have this CA, not adding again");
28872914
FreeTrustedPeer(peerCert, cm->heap);

wolfssl/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2647,6 +2647,14 @@ struct WOLFSSL_CERT_MANAGER {
26472647
|| defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
26482648
byte ocspMustStaple:1; /* server must respond with staple */
26492649
#endif
2650+
/* Tracks which resources were successfully initialized so that
2651+
* DoCertManagerFree can dispose of them safely even when construction
2652+
* fails partway through. */
2653+
WC_BITFIELD caLockInit:1; /* caLock has been initialized */
2654+
#ifdef WOLFSSL_TRUST_PEER_CERT
2655+
WC_BITFIELD tpLockInit:1; /* tpLock has been initialized */
2656+
#endif
2657+
WC_BITFIELD refInit:1; /* ref has been initialized */
26502658

26512659
#ifndef NO_RSA
26522660
short minRsaKeySz; /* minimum allowed RSA key size */

0 commit comments

Comments
 (0)