Skip to content

Commit c92d258

Browse files
Merge pull request #6887 from julek-wolfssl/zd/16849
Implement untrusted certs in wolfSSL_X509_STORE_CTX_init
2 parents 8569e76 + d13d446 commit c92d258

5 files changed

Lines changed: 229 additions & 63 deletions

File tree

src/ssl.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24285,6 +24285,38 @@ WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk)
2428524285
return NULL;
2428624286
}
2428724287

24288+
24289+
WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk)
24290+
{
24291+
24292+
WOLFSSL_STACK* ret = NULL;
24293+
WOLFSSL_STACK** prev = &ret;
24294+
24295+
WOLFSSL_ENTER("wolfSSL_shallow_sk_dup");
24296+
24297+
for (; sk != NULL; sk = sk->next) {
24298+
WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap);
24299+
24300+
if (!cur) {
24301+
WOLFSSL_MSG("wolfSSL_sk_new_node error");
24302+
goto error;
24303+
}
24304+
24305+
XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK));
24306+
cur->next = NULL;
24307+
24308+
*prev = cur;
24309+
prev = &cur->next;
24310+
}
24311+
return ret;
24312+
24313+
error:
24314+
if (ret) {
24315+
wolfSSL_sk_free(ret);
24316+
}
24317+
return NULL;
24318+
}
24319+
2428824320
/* Free the just the stack structure */
2428924321
void wolfSSL_sk_free(WOLFSSL_STACK* sk)
2429024322
{

src/ssl_certman.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,7 @@ int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
16481648
if (ret == WOLFSSL_SUCCESS) {
16491649
/* Disable CRL checking. */
16501650
cm->crlEnabled = 0;
1651+
cm->crlCheckAll = 0;
16511652
}
16521653

16531654
return ret;

src/x509_str.c

Lines changed: 80 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,40 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
8484
#endif
8585

8686
ctx->chain = sk;
87-
/* Add intermediate certificates from stack to store */
88-
while (sk != NULL) {
89-
WOLFSSL_X509* x509_cert = sk->data.x509;
90-
if (x509_cert != NULL && x509_cert->isCa) {
91-
ret = wolfSSL_X509_STORE_add_cert(store, x509_cert);
92-
if (ret < 0) {
93-
return WOLFSSL_FAILURE;
87+
/* Add intermediate certs, that verify to a loaded CA, to the store */
88+
if (sk != NULL) {
89+
byte addedAtLeastOne = 1;
90+
WOLF_STACK_OF(WOLFSSL_X509)* head = wolfSSL_shallow_sk_dup(sk);
91+
if (head == NULL)
92+
return WOLFSSL_FAILURE;
93+
while (addedAtLeastOne) {
94+
WOLF_STACK_OF(WOLFSSL_X509)* cur = head;
95+
WOLF_STACK_OF(WOLFSSL_X509)** prev = &head;
96+
addedAtLeastOne = 0;
97+
while (cur) {
98+
WOLFSSL_X509* cert = cur->data.x509;
99+
if (cert != NULL && cert->derCert != NULL &&
100+
wolfSSL_CertManagerVerifyBuffer(store->cm,
101+
cert->derCert->buffer,
102+
cert->derCert->length,
103+
WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) {
104+
ret = wolfSSL_X509_STORE_add_cert(store, cert);
105+
if (ret < 0) {
106+
wolfSSL_sk_free(head);
107+
return WOLFSSL_FAILURE;
108+
}
109+
addedAtLeastOne = 1;
110+
*prev = cur->next;
111+
wolfSSL_sk_free_node(cur);
112+
cur = *prev;
113+
}
114+
else {
115+
prev = &cur->next;
116+
cur = cur->next;
117+
}
94118
}
95119
}
96-
sk = sk->next;
120+
wolfSSL_sk_free(head);
97121
}
98122

99123
ctx->sesChain = NULL;
@@ -140,7 +164,9 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
140164
}
141165
}
142166

143-
167+
/* Its recommended to use a full free -> init cycle of all the objects
168+
* because wolfSSL_X509_STORE_CTX_init may modify the store too which doesn't
169+
* get reset here. */
144170
void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx)
145171
{
146172
if (ctx != NULL) {
@@ -168,7 +194,7 @@ int GetX509Error(int e)
168194
{
169195
switch (e) {
170196
case ASN_BEFORE_DATE_E:
171-
return WOLFSSL_X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
197+
return WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID;
172198
case ASN_AFTER_DATE_E:
173199
return WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED;
174200
case ASN_NO_SIGNER_E: /* get issuer error if no CA found locally */
@@ -185,6 +211,9 @@ int GetX509Error(int e)
185211
return WOLFSSL_X509_V_ERR_CERT_SIGNATURE_FAILURE;
186212
case CRL_CERT_REVOKED:
187213
return WOLFSSL_X509_V_ERR_CERT_REVOKED;
214+
case 0:
215+
case 1:
216+
return 0;
188217
default:
189218
#ifdef HAVE_WOLFSSL_MSG_EX
190219
WOLFSSL_MSG_EX("Error not configured or implemented yet: %d", e);
@@ -195,6 +224,19 @@ int GetX509Error(int e)
195224
}
196225
}
197226

227+
static void SetupStoreCtxError(WOLFSSL_X509_STORE_CTX* ctx, int ret)
228+
{
229+
int depth = 0;
230+
int error = GetX509Error(ret);
231+
232+
/* Set error depth */
233+
if (ctx->chain)
234+
depth = (int)ctx->chain->num;
235+
236+
wolfSSL_X509_STORE_CTX_set_error(ctx, error);
237+
wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
238+
}
239+
198240
/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX
199241
* returns 0 on success or < 0 on failure.
200242
*/
@@ -204,66 +246,39 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
204246

205247
if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL
206248
&& ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) {
207-
int ret = 0;
208-
int depth = 0;
209-
int error;
210-
#ifndef NO_ASN_TIME
211-
byte *afterDate, *beforeDate;
212-
#endif
213-
214-
ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
249+
int ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
215250
ctx->current_cert->derCert->buffer,
216251
ctx->current_cert->derCert->length,
217252
WOLFSSL_FILETYPE_ASN1);
218-
/* If there was an error, process it and add it to CTX */
219-
if (ret < 0) {
220-
/* Get corresponding X509 error */
221-
error = GetX509Error(ret);
222-
/* Set error depth */
223-
if (ctx->chain)
224-
depth = (int)ctx->chain->num;
225-
226-
wolfSSL_X509_STORE_CTX_set_error(ctx, error);
227-
wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
228-
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
229-
if (ctx->store && ctx->store->verify_cb)
230-
ctx->store->verify_cb(0, ctx);
231-
#endif
232-
}
253+
SetupStoreCtxError(ctx, ret);
233254

234255
#ifndef NO_ASN_TIME
235-
error = 0;
236-
/* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or
237-
ASN_BEFORE_DATE_E if there are no additional errors found in the
238-
cert. Therefore, check if the cert is expired or not yet valid
239-
in order to return the correct expected error. */
240-
afterDate = ctx->current_cert->notAfter.data;
241-
beforeDate = ctx->current_cert->notBefore.data;
242-
243-
if (XVALIDATE_DATE(afterDate, (byte)ctx->current_cert->notAfter.type,
244-
AFTER) < 1) {
245-
error = WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED;
246-
}
247-
else if (XVALIDATE_DATE(beforeDate,
248-
(byte)ctx->current_cert->notBefore.type, BEFORE) < 1) {
249-
error = WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID;
256+
if (ret != ASN_BEFORE_DATE_E && ret != ASN_AFTER_DATE_E) {
257+
/* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or
258+
ASN_BEFORE_DATE_E if there are no additional errors found in the
259+
cert. Therefore, check if the cert is expired or not yet valid
260+
in order to return the correct expected error. */
261+
byte *afterDate = ctx->current_cert->notAfter.data;
262+
byte *beforeDate = ctx->current_cert->notBefore.data;
263+
264+
if (XVALIDATE_DATE(afterDate,
265+
(byte)ctx->current_cert->notAfter.type, AFTER) < 1) {
266+
ret = ASN_AFTER_DATE_E;
267+
}
268+
else if (XVALIDATE_DATE(beforeDate,
269+
(byte)ctx->current_cert->notBefore.type, BEFORE) < 1) {
270+
ret = ASN_BEFORE_DATE_E;
271+
}
272+
SetupStoreCtxError(ctx, ret);
250273
}
274+
#endif
251275

252-
if (error != 0 ) {
253-
wolfSSL_X509_STORE_CTX_set_error(ctx, error);
254-
wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
255-
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
256-
if (ctx->store && ctx->store->verify_cb)
257-
ctx->store->verify_cb(0, ctx);
258-
#endif
259-
}
276+
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
277+
if (ctx->store && ctx->store->verify_cb)
278+
ret = ctx->store->verify_cb(ret >= 0 ? 1 : 0, ctx) == 1 ? 0 : -1;
260279
#endif
261280

262-
/* OpenSSL returns 0 when a chain can't be built */
263-
if (ret == ASN_NO_SIGNER_E)
264-
return WOLFSSL_FAILURE;
265-
else
266-
return ret;
281+
return ret >= 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
267282
}
268283
return WOLFSSL_FATAL_ERROR;
269284
}
@@ -1029,8 +1044,11 @@ WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str,
10291044

10301045
#ifdef HAVE_CRL
10311046
if (str->cm->crl == NULL) {
1047+
/* Workaround to allocate the internals to load CRL's but don't enable
1048+
* CRL checking by default */
10321049
if (wolfSSL_CertManagerEnableCRL(str->cm, WOLFSSL_CRL_CHECK)
1033-
!= WOLFSSL_SUCCESS) {
1050+
!= WOLFSSL_SUCCESS ||
1051+
wolfSSL_CertManagerDisableCRL(str->cm) != WOLFSSL_SUCCESS) {
10341052
WOLFSSL_MSG("Enable CRL failed");
10351053
wolfSSL_CTX_free(ctx);
10361054
return WOLFSSL_FAILURE;

tests/api.c

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35531,6 +35531,118 @@ static int test_wolfSSL_X509_STORE_CTX(void)
3553135531
return EXPECT_RESULT();
3553235532
}
3553335533

35534+
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA)
35535+
static int test_X509_STORE_untrusted_load_cert_to_stack(const char* filename,
35536+
STACK_OF(X509)* chain)
35537+
{
35538+
EXPECT_DECLS;
35539+
XFILE fp = XBADFILE;
35540+
X509* cert = NULL;
35541+
35542+
ExpectTrue((fp = XFOPEN(filename, "rb"))
35543+
!= XBADFILE);
35544+
ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 ));
35545+
if (fp != XBADFILE) {
35546+
XFCLOSE(fp);
35547+
fp = XBADFILE;
35548+
}
35549+
ExpectIntEQ(sk_X509_push(chain, cert), 1);
35550+
if (EXPECT_FAIL())
35551+
X509_free(cert);
35552+
35553+
return EXPECT_RESULT();
35554+
}
35555+
35556+
static int test_X509_STORE_untrusted_certs(const char** filenames, int ret,
35557+
int err, int loadCA)
35558+
{
35559+
EXPECT_DECLS;
35560+
X509_STORE_CTX* ctx = NULL;
35561+
X509_STORE* str = NULL;
35562+
XFILE fp = XBADFILE;
35563+
X509* cert = NULL;
35564+
STACK_OF(X509)* untrusted = NULL;
35565+
35566+
ExpectTrue((fp = XFOPEN("./certs/intermediate/server-int-cert.pem", "rb"))
35567+
!= XBADFILE);
35568+
ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 ));
35569+
if (fp != XBADFILE) {
35570+
XFCLOSE(fp);
35571+
fp = XBADFILE;
35572+
}
35573+
35574+
ExpectNotNull(str = X509_STORE_new());
35575+
ExpectNotNull(ctx = X509_STORE_CTX_new());
35576+
ExpectNotNull(untrusted = sk_X509_new_null());
35577+
35578+
ExpectIntEQ(X509_STORE_set_flags(str, 0), 1);
35579+
if (loadCA) {
35580+
ExpectIntEQ(X509_STORE_load_locations(str, "./certs/ca-cert.pem", NULL),
35581+
1);
35582+
}
35583+
for (; *filenames; filenames++) {
35584+
ExpectIntEQ(test_X509_STORE_untrusted_load_cert_to_stack(*filenames,
35585+
untrusted), TEST_SUCCESS);
35586+
}
35587+
35588+
ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1);
35589+
ExpectIntEQ(X509_verify_cert(ctx), ret);
35590+
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), err);
35591+
35592+
X509_free(cert);
35593+
X509_STORE_free(str);
35594+
X509_STORE_CTX_free(ctx);
35595+
sk_X509_pop_free(untrusted, NULL);
35596+
35597+
return EXPECT_RESULT();
35598+
}
35599+
#endif
35600+
35601+
static int test_X509_STORE_untrusted(void)
35602+
{
35603+
EXPECT_DECLS;
35604+
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA)
35605+
const char* untrusted1[] = {
35606+
"./certs/intermediate/ca-int2-cert.pem",
35607+
NULL
35608+
};
35609+
const char* untrusted2[] = {
35610+
"./certs/intermediate/ca-int-cert.pem",
35611+
"./certs/intermediate/ca-int2-cert.pem",
35612+
NULL
35613+
};
35614+
const char* untrusted3[] = {
35615+
"./certs/intermediate/ca-int-cert.pem",
35616+
"./certs/intermediate/ca-int2-cert.pem",
35617+
"./certs/ca-cert.pem",
35618+
NULL
35619+
};
35620+
/* Adding unrelated certs that should be ignored */
35621+
const char* untrusted4[] = {
35622+
"./certs/client-ca.pem",
35623+
"./certs/intermediate/ca-int-cert.pem",
35624+
"./certs/server-cert.pem",
35625+
"./certs/intermediate/ca-int2-cert.pem",
35626+
NULL
35627+
};
35628+
35629+
/* Only immediate issuer in untrusted chaing. Fails since can't build chain
35630+
* to loaded CA. */
35631+
ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted1, 0,
35632+
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 1), TEST_SUCCESS);
35633+
/* Succeeds because path to loaded CA is available. */
35634+
ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted2, 1, 0, 1),
35635+
TEST_SUCCESS);
35636+
/* Fails because root CA is in the untrusted stack */
35637+
ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 0,
35638+
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 0), TEST_SUCCESS);
35639+
/* Succeeds because path to loaded CA is available. */
35640+
ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted4, 1, 0, 1),
35641+
TEST_SUCCESS);
35642+
#endif
35643+
return EXPECT_RESULT();
35644+
}
35645+
3553435646
static int test_wolfSSL_X509_STORE_set_flags(void)
3553535647
{
3553635648
EXPECT_DECLS;
@@ -51492,7 +51604,8 @@ static int test_X509_LOOKUP_add_dir(void)
5149251604

5149351605
/* Now we SHOULD get CRL_MISSING, because we looked for PEM
5149451606
* in dir containing only ASN1/DER. */
51495-
ExpectIntEQ(X509_verify_cert(storeCtx), CRL_MISSING);
51607+
ExpectIntEQ(X509_verify_cert(storeCtx), WOLFSSL_FAILURE);
51608+
ExpectIntEQ(X509_STORE_CTX_get_error(storeCtx), CRL_MISSING);
5149651609

5149751610
X509_CRL_free(crl);
5149851611
X509_STORE_free(store);
@@ -67697,6 +67810,7 @@ TEST_CASE testCases[] = {
6769767810
TEST_DECL(test_wolfSSL_TBS),
6769867811

6769967812
TEST_DECL(test_wolfSSL_X509_STORE_CTX),
67813+
TEST_DECL(test_X509_STORE_untrusted),
6770067814
TEST_DECL(test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup),
6770167815
TEST_DECL(test_wolfSSL_X509_STORE_CTX_get0_current_issuer),
6770267816
TEST_DECL(test_wolfSSL_X509_STORE_set_flags),

wolfssl/ssl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,7 @@ WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap);
15261526
WOLFSSL_API void wolfSSL_sk_free(WOLFSSL_STACK* sk);
15271527
WOLFSSL_API void wolfSSL_sk_free_node(WOLFSSL_STACK* in);
15281528
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk);
1529+
WOLFSSL_API WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk);
15291530
WOLFSSL_API int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in);
15301531
WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx);
15311532
WOLFSSL_API int wolfSSL_sk_push(WOLFSSL_STACK *st, const void *data);

0 commit comments

Comments
 (0)