Skip to content

Commit 96dba11

Browse files
Retry all certificates passed into wolfSSL_X509_verify_cert until a valid chain is found, rather than failing out on the first invalid chain. This allows for registering multiple certs with the same subject key, ie. alt cert chains.
1 parent be5b62b commit 96dba11

File tree

3 files changed

+107
-3
lines changed

3 files changed

+107
-3
lines changed

src/ssl.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6092,6 +6092,53 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
60926092
return ret == 0 ? WOLFSSL_SUCCESS : ret;
60936093
}
60946094

6095+
/* Removes the CA with the passed in subject hash from the cert manager's CA cert store. */
6096+
int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash)
6097+
{
6098+
Signer* current;
6099+
Signer* prev;
6100+
int ret = 0;
6101+
word32 row;
6102+
6103+
if (cm == NULL || hash == NULL) {
6104+
return ret;
6105+
}
6106+
6107+
row = HashSigner(hash);
6108+
6109+
if (wc_LockMutex(&cm->caLock) != 0) {
6110+
return ret;
6111+
}
6112+
current = cm->caTable[row];
6113+
prev = current;
6114+
while (current) {
6115+
byte* subjectHash;
6116+
6117+
#ifndef NO_SKID
6118+
subjectHash = current->subjectKeyIdHash;
6119+
#else
6120+
subjectHash = current->subjectNameHash;
6121+
#endif
6122+
6123+
if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
6124+
if (current == cm->caTable[row]) {
6125+
cm->caTable[row] = cm->caTable[row]->next;
6126+
}
6127+
else {
6128+
prev->next = current->next;
6129+
}
6130+
FreeSigner(current, cm->heap);
6131+
ret = 1;
6132+
break;
6133+
}
6134+
prev = current;
6135+
current = current->next;
6136+
}
6137+
wc_UnLockMutex(&cm->caLock);
6138+
6139+
return ret;
6140+
}
6141+
60956142
#endif /* !NO_CERTS */
60966143

60976144

src/x509_str.c

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#ifdef OPENSSL_EXTRA
3535
static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer,
3636
WOLFSSL_STACK *certs, WOLFSSL_X509 *x);
37+
static int X509StorePopCert(WOLFSSL_STACK *certs_stack, WOLFSSL_STACK *dest_stack,
38+
WOLFSSL_X509 *cert);
3739
static int X509StoreAddCa(WOLFSSL_X509_STORE* store,
3840
WOLFSSL_X509* x509, int type);
3941
#endif
@@ -415,10 +417,12 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
415417
int i = 0;
416418
int numInterAdd = 0;
417419
int depth = 0;
420+
int origDepth = 0;
418421
WOLFSSL_X509 *issuer = NULL;
419422
WOLFSSL_X509 *orig = NULL;
420423
WOLF_STACK_OF(WOLFSSL_X509)* certs = NULL;
421424
WOLF_STACK_OF(WOLFSSL_X509)* certsToUse = NULL;
425+
WOLF_STACK_OF(WOLFSSL_X509)* failedCerts = NULL;
422426
WOLFSSL_ENTER("wolfSSL_X509_verify_cert");
423427

424428
if (ctx == NULL || ctx->store == NULL || ctx->store->cm == NULL
@@ -427,6 +431,10 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
427431
}
428432

429433
certs = ctx->store->certs;
434+
if (certs == NULL) {
435+
return WOLFSSL_FATAL_ERROR;
436+
}
437+
430438
if (ctx->setTrustedSk != NULL) {
431439
certs = ctx->setTrustedSk;
432440
}
@@ -450,6 +458,10 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
450458
}
451459
ctx->chain = wolfSSL_sk_X509_new_null();
452460

461+
failedCerts = wolfSSL_sk_X509_new_null();
462+
if (!failedCerts)
463+
return WOLFSSL_FATAL_ERROR;
464+
453465
if (ctx->depth > 0) {
454466
depth = ctx->depth + 1;
455467
}
@@ -458,6 +470,7 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
458470
}
459471

460472
orig = ctx->current_cert;
473+
origDepth = depth;
461474
while(done == 0 && depth > 0) {
462475
issuer = NULL;
463476

@@ -491,12 +504,14 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
491504
ret = X509StoreAddCa(ctx->store, issuer,
492505
WOLFSSL_TEMP_CA);
493506
if (ret != WOLFSSL_SUCCESS) {
494-
goto exit;
507+
goto retry;
495508
}
496509
added = 1;
497510
ret = X509StoreVerifyCert(ctx);
498511
if (ret != WOLFSSL_SUCCESS) {
499-
goto exit;
512+
if ((origDepth - depth) <= 1)
513+
added = 0;
514+
goto retry;
500515
}
501516
/* Add it to the current chain and look at the issuer cert next */
502517
wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert);
@@ -515,8 +530,9 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
515530
(added == 1)) {
516531
wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert);
517532
ret = WOLFSSL_SUCCESS;
533+
} else {
534+
goto retry;
518535
}
519-
goto exit;
520536
}
521537

522538
/* Cert verified, finish building the chain */
@@ -548,6 +564,19 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
548564
}
549565

550566
depth--;
567+
continue;
568+
569+
retry:
570+
/* Current certificate failed, but it is possible there is an alternative
571+
* cert with the same subject key which will work. Retry until all
572+
* possible candidate certs are exhausted. */
573+
WOLFSSL_MSG("X509_verify_cert current cert failed, retrying with other certs.");
574+
RemoveCA(ctx->store->cm, ctx->current_cert->subjKeyId);
575+
X509StorePopCert(certs, failedCerts, ctx->current_cert);
576+
if (numInterAdd > 0)
577+
numInterAdd--;
578+
ctx->current_cert = wolfSSL_sk_X509_pop(ctx->chain);
579+
depth++;
551580
}
552581

553582
exit:
@@ -572,6 +601,17 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
572601
wolfSSL_sk_X509_free(certsToUse);
573602
}
574603

604+
/* Copy back failed certs if verification failed. */
605+
if (ret != WOLFSSL_SUCCESS) {
606+
while (wolfSSL_sk_X509_num(failedCerts) > 0)
607+
{
608+
wolfSSL_sk_X509_push(certs, wolfSSL_sk_X509_pop(failedCerts));
609+
}
610+
}
611+
if (failedCerts) {
612+
wolfSSL_sk_X509_free(failedCerts);
613+
}
614+
575615
return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
576616
}
577617

@@ -1055,6 +1095,22 @@ static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer,
10551095
return WOLFSSL_FAILURE;
10561096
}
10571097

1098+
static int X509StorePopCert(WOLFSSL_STACK *certs_stack, WOLFSSL_STACK *dest_stack, WOLFSSL_X509 *cert) {
1099+
int i;
1100+
1101+
if (certs_stack == NULL || dest_stack == NULL || cert == NULL)
1102+
return WOLFSSL_FATAL_ERROR;
1103+
1104+
for (i = 0; i < wolfSSL_sk_X509_num(certs_stack); i++) {
1105+
if (wolfSSL_sk_X509_value(certs_stack, i) == cert) {
1106+
wolfSSL_sk_X509_push(dest_stack, wolfSSL_sk_pop_node(certs_stack, i));
1107+
return WOLFSSL_SUCCESS;
1108+
}
1109+
}
1110+
1111+
return WOLFSSL_FAILURE;
1112+
}
1113+
10581114
#endif
10591115

10601116
/******************************************************************************

wolfssl/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4260,6 +4260,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
42604260
WOLFSSL_LOCAL int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s);
42614261
WOLFSSL_LOCAL
42624262
int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify);
4263+
WOLFSSL_LOCAL int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash);
42634264
WOLFSSL_LOCAL
42644265
int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash);
42654266
#ifdef WOLFSSL_TRUST_PEER_CERT

0 commit comments

Comments
 (0)