@@ -404,6 +404,64 @@ static int addAllButSelfSigned(WOLF_STACK_OF(WOLFSSL_X509)*to,
404404 return ret ;
405405}
406406
407+ static int X509StoreRemoveCa (WOLFSSL_X509_STORE * store ,
408+ WOLFSSL_X509 * x509 , int type ) {
409+ int result = WC_NO_ERR_TRACE (WOLFSSL_FATAL_ERROR );
410+ byte hash [KEYID_SIZE ];
411+
412+ if (store != NULL && x509 != NULL && x509 -> derCert != NULL ) {
413+ result = GetHashId (x509 -> subjKeyId , (int )x509 -> subjKeyIdSz ,
414+ hash , HashIdAlg (x509 -> sigOID ));
415+ if (result ) {
416+ result = WOLFSSL_FATAL_ERROR ;
417+ } else {
418+ result = RemoveCA (store -> cm , hash , type );
419+ }
420+ }
421+
422+ return result ;
423+ }
424+
425+ static int X509StoreMoveCert (WOLFSSL_STACK * certs_stack ,
426+ WOLFSSL_STACK * dest_stack ,
427+ WOLFSSL_X509 * cert ) {
428+ int i ;
429+
430+ if (certs_stack == NULL || dest_stack == NULL || cert == NULL )
431+ return WOLFSSL_FATAL_ERROR ;
432+
433+ for (i = 0 ; i < wolfSSL_sk_X509_num (certs_stack ); i ++ ) {
434+ if (wolfSSL_sk_X509_value (certs_stack , i ) == cert ) {
435+ wolfSSL_sk_X509_push (dest_stack ,
436+ (WOLFSSL_X509 * )wolfSSL_sk_pop_node (certs_stack , i ));
437+ return WOLFSSL_SUCCESS ;
438+ }
439+ }
440+
441+ return WOLFSSL_FAILURE ;
442+ }
443+
444+
445+ /* Current certificate failed, but it is possible there is an
446+ * alternative cert with the same subject key which will work.
447+ * Retry until all possible candidate certs are exhausted. */
448+ static int X509VerifyCertSetupRetry (WOLFSSL_X509_STORE_CTX * ctx ,
449+ WOLF_STACK_OF (WOLFSSL_X509 )* certs , WOLF_STACK_OF (WOLFSSL_X509 )* failed ,
450+ int * depth , int origDepth ) {
451+ int ret = WC_NO_ERR_TRACE (WOLFSSL_FAILURE );
452+
453+ WOLFSSL_MSG ("X509_verify_cert current cert failed, "
454+ "retrying with other certs." );
455+ ret = X509StoreRemoveCa (ctx -> store , ctx -> current_cert ,
456+ WOLFSSL_TEMP_CA );
457+ X509StoreMoveCert (certs , failed , ctx -> current_cert );
458+ ctx -> current_cert = wolfSSL_sk_X509_pop (ctx -> chain );
459+ if (* depth < origDepth )
460+ * depth += 1 ;
461+
462+ return ret ;
463+ }
464+
407465/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX
408466 * returns 1 on success or <= 0 on failure.
409467 */
@@ -414,11 +472,14 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
414472 int added = 0 ;
415473 int i = 0 ;
416474 int numInterAdd = 0 ;
475+ int numFailedCerts = 0 ;
417476 int depth = 0 ;
477+ int origDepth = 0 ;
418478 WOLFSSL_X509 * issuer = NULL ;
419479 WOLFSSL_X509 * orig = NULL ;
420480 WOLF_STACK_OF (WOLFSSL_X509 )* certs = NULL ;
421481 WOLF_STACK_OF (WOLFSSL_X509 )* certsToUse = NULL ;
482+ WOLF_STACK_OF (WOLFSSL_X509 )* failedCerts = NULL ;
422483 WOLFSSL_ENTER ("wolfSSL_X509_verify_cert" );
423484
424485 if (ctx == NULL || ctx -> store == NULL || ctx -> store -> cm == NULL
@@ -427,6 +488,7 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
427488 }
428489
429490 certs = ctx -> store -> certs ;
491+
430492 if (ctx -> setTrustedSk != NULL ) {
431493 certs = ctx -> setTrustedSk ;
432494 }
@@ -450,6 +512,10 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
450512 }
451513 ctx -> chain = wolfSSL_sk_X509_new_null ();
452514
515+ failedCerts = wolfSSL_sk_X509_new_null ();
516+ if (!failedCerts )
517+ return WOLFSSL_FATAL_ERROR ;
518+
453519 if (ctx -> depth > 0 ) {
454520 depth = ctx -> depth + 1 ;
455521 }
@@ -458,6 +524,7 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
458524 }
459525
460526 orig = ctx -> current_cert ;
527+ origDepth = depth ;
461528 while (done == 0 && depth > 0 ) {
462529 issuer = NULL ;
463530
@@ -486,23 +553,28 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
486553 goto exit ;
487554 }
488555 }
489- } else {
556+ } else
490557 #endif
491- ret = X509StoreAddCa (ctx -> store , issuer ,
492- WOLFSSL_TEMP_CA );
493- if (ret != WOLFSSL_SUCCESS ) {
494- goto exit ;
495- }
496- added = 1 ;
497- ret = X509StoreVerifyCert (ctx );
498- if (ret != WOLFSSL_SUCCESS ) {
499- goto exit ;
500- }
501- /* Add it to the current chain and look at the issuer cert next */
502- wolfSSL_sk_X509_push (ctx -> chain , ctx -> current_cert );
503- #if defined(OPENSSL_ALL ) || defined(WOLFSSL_QT )
558+ {
559+ ret = X509StoreAddCa (ctx -> store , issuer ,
560+ WOLFSSL_TEMP_CA );
561+ if (ret != WOLFSSL_SUCCESS ) {
562+ X509VerifyCertSetupRetry (ctx , certs , failedCerts ,
563+ & depth , origDepth );
564+ continue ;
565+ }
566+ added = 1 ;
567+ ret = X509StoreVerifyCert (ctx );
568+ if (ret != WOLFSSL_SUCCESS ) {
569+ if ((origDepth - depth ) <= 1 )
570+ added = 0 ;
571+ X509VerifyCertSetupRetry (ctx , certs , failedCerts ,
572+ & depth , origDepth );
573+ continue ;
574+ }
575+ /* Add it to the current chain and look at the issuer cert next */
576+ wolfSSL_sk_X509_push (ctx -> chain , ctx -> current_cert );
504577 }
505- #endif
506578 ctx -> current_cert = issuer ;
507579 }
508580 else if (ret == WC_NO_ERR_TRACE (WOLFSSL_FAILURE )) {
@@ -515,8 +587,11 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
515587 (added == 1 )) {
516588 wolfSSL_sk_X509_push (ctx -> chain , ctx -> current_cert );
517589 ret = WOLFSSL_SUCCESS ;
590+ } else {
591+ X509VerifyCertSetupRetry (ctx , certs , failedCerts ,
592+ & depth , origDepth );
593+ continue ;
518594 }
519- goto exit ;
520595 }
521596
522597 /* Cert verified, finish building the chain */
@@ -551,6 +626,14 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
551626 }
552627
553628exit :
629+ /* Copy back failed certs. */
630+ numFailedCerts = wolfSSL_sk_X509_num (failedCerts );
631+ for (i = 0 ; i < numFailedCerts ; i ++ )
632+ {
633+ wolfSSL_sk_X509_push (certs , wolfSSL_sk_X509_pop (failedCerts ));
634+ }
635+ wolfSSL_sk_X509_pop_free (failedCerts , NULL );
636+
554637 /* Remove additional intermediates from init from the store */
555638 if (ctx != NULL && numInterAdd > 0 ) {
556639 for (i = 0 ; i < numInterAdd ; i ++ ) {
@@ -1390,7 +1473,6 @@ static int X509StoreAddCa(WOLFSSL_X509_STORE* store,
13901473 return result ;
13911474}
13921475
1393-
13941476int wolfSSL_X509_STORE_add_cert (WOLFSSL_X509_STORE * store , WOLFSSL_X509 * x509 )
13951477{
13961478 int result = WC_NO_ERR_TRACE (WOLFSSL_FATAL_ERROR );
0 commit comments