Skip to content

Commit e40e852

Browse files
handle certificate chains
1 parent 69e1cde commit e40e852

5 files changed

Lines changed: 221 additions & 93 deletions

File tree

examples/echoserver/echoserver.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,11 +1898,14 @@ static int wsUserAuth(byte authType,
18981898
wc_Sha256Hash(authData->sf.publicKey.publicKey,
18991899
authData->sf.publicKey.publicKeySz,
19001900
authHash);
1901-
#if defined(WOLFSSH_CERTS) && !defined(WOLFSSH_NO_FPKI)
1902-
/* Display FPKI info UUID and FASC-N */
1901+
#if defined(WOLFSSH_CERTS) && !defined(WOLFSSH_NO_FPKI) && \
1902+
defined(WOLFSSL_FPKI)
1903+
/* Display FPKI info UUID and FASC-N, getter function for FASC-N and
1904+
* UUID are dependent on wolfSSL version newer than 5.3.0 so gatting
1905+
* on the macro WOLFSSL_FPKI here too */
19031906
if (authData->sf.publicKey.isCert) {
19041907
DecodedCert cert;
1905-
byte* uuid;
1908+
byte* uuid = NULL;
19061909
word32 fascnSz;
19071910
word32 uuidSz;
19081911
word32 i;

src/certman.c

Lines changed: 144 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -86,33 +86,36 @@ struct WOLFSSH_CERTMAN {
8686

8787
static WOLFSSH_CERTMAN* _CertMan_init(WOLFSSH_CERTMAN* cm, void* heap)
8888
{
89+
WOLFSSH_CERTMAN* ret = NULL;
8990
WLOG_ENTER();
9091

91-
if (cm != NULL) {
92-
WMEMSET(cm, 0, sizeof *cm);
93-
cm->cm = wolfSSL_CertManagerNew_ex(heap);
94-
if (cm->cm != NULL) {
95-
int ret;
92+
ret = cm;
93+
if (ret != NULL) {
94+
WMEMSET(ret, 0, sizeof(WOLFSSH_CERTMAN));
95+
ret->cm = wolfSSL_CertManagerNew_ex(heap);
96+
if (ret->cm == NULL) {
97+
ret = NULL;
98+
}
99+
#ifdef HAVE_OCSP
100+
else {
101+
int err;
96102

97-
ret = wolfSSL_CertManagerEnableOCSP(cm->cm,
103+
err = wolfSSL_CertManagerEnableOCSP(ret->cm,
98104
WOLFSSL_OCSP_CHECKALL);
99-
100-
if (ret == WOLFSSL_SUCCESS) {
105+
if (err == WOLFSSL_SUCCESS) {
101106
WLOG(WS_LOG_CERTMAN, "Enabled OCSP");
102107
}
103108
else {
104109
WLOG(WS_LOG_CERTMAN, "Couldn't enable OCSP");
105-
wolfSSL_CertManagerFree(cm->cm);
106-
cm = NULL;
110+
wolfSSL_CertManagerFree(ret->cm);
111+
ret = NULL;
107112
}
108113
}
109-
else {
110-
cm = NULL;
111-
}
114+
#endif
112115
}
113116

114-
WLOG_LEAVE_PTR(cm);
115-
return cm;
117+
WLOG_LEAVE_PTR(ret);
118+
return ret;
116119
}
117120

118121

@@ -190,59 +193,148 @@ enum {
190193
};
191194
#endif /* WOLFSSH_NO_FPKI */
192195

193-
int wolfSSH_CERTMAN_VerifyCert_buffer(WOLFSSH_CERTMAN* cm,
194-
const unsigned char* cert, word32 certSz)
196+
/* if handling a chain it is expected to be the leaf cert first followed by
197+
* intermediates and CA last (CA may be ommited) */
198+
int wolfSSH_CERTMAN_VerifyCerts_buffer(WOLFSSH_CERTMAN* cm,
199+
const unsigned char* certs, word32 certSz, word32 certsCount)
195200
{
196201
int ret = WS_SUCCESS;
202+
int idx;
203+
204+
unsigned char **certLoc; /* locations of certificate start */
205+
word32 *certLen; /* size of certificate, in sync with certLoc */
206+
207+
unsigned char *currentPt;
208+
word32 currentSz;
197209

198210
WLOG_ENTER();
199211

200-
if (ret == WS_SUCCESS) {
201-
ret = wolfSSL_CertManagerVerifyBuffer(cm->cm, cert, certSz,
202-
WOLFSSL_FILETYPE_ASN1);
212+
certLoc = (unsigned char**)WMALLOC(certsCount * sizeof(unsigned char*),
213+
cm->heap, DYNTYPE_CERT);
214+
certLen = (word32*)WMALLOC(certsCount * sizeof(word32), cm->heap,
215+
DYNTYPE_CERT);
203216

204-
if (ret == WOLFSSL_SUCCESS) {
205-
ret = WS_SUCCESS;
206-
}
207-
else if (ret == ASN_NO_SIGNER_E) {
208-
WLOG(WS_LOG_CERTMAN, "cert verify: no signer");
209-
ret = WS_CERT_NO_SIGNER_E;
210-
}
211-
else if (ret == ASN_AFTER_DATE_E) {
212-
WLOG(WS_LOG_CERTMAN, "cert verify: expired");
213-
ret = WS_CERT_EXPIRED_E;
214-
}
215-
else if (ret == ASN_SIG_CONFIRM_E) {
216-
WLOG(WS_LOG_CERTMAN, "cert verify: bad sig");
217-
ret = WS_CERT_SIG_CONFIRM_E;
217+
currentPt = (unsigned char*)certs; /* set initial certificate pointer */
218+
currentSz = 0;
219+
220+
for (idx = 0; idx < (int)certsCount; idx++) {
221+
word32 sz = 0;
222+
certLoc[idx] = currentPt;
223+
224+
/* get the size of the certificate from first sequence */
225+
if (currentSz + MAX_SEQ_SZ >= certSz) {
226+
ret = WS_BUFFER_E;
227+
break;
218228
}
219229
else {
220-
WLOG(WS_LOG_CERTMAN, "cert verify: other error (%d)", ret);
221-
ret = WS_CERT_OTHER_E;
230+
/* at this point there is at least 5 bytes in currentPt */
231+
if (currentPt[sz] != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
232+
WLOG(WS_LOG_CERTMAN, "no cert sequence to get length from");
233+
ret = ASN_PARSE_E;
234+
break;
235+
}
236+
sz++;
237+
238+
if (ret == WS_SUCCESS) {
239+
if (currentPt[sz] >= ASN_LONG_LENGTH) {
240+
word32 bytes = currentPt[sz++] & 0x7F;
241+
if (bytes > MAX_LENGTH_SZ) {
242+
WLOG(WS_LOG_CERTMAN, "length found is too large!");
243+
ret = ASN_PARSE_E;
244+
break;
245+
}
246+
else {
247+
byte b;
248+
certLen[idx] = 0;
249+
for (; bytes > 0; bytes--) {
250+
b = currentPt[sz++];
251+
certLen[idx] = (certLen[idx] << 8) | b;
252+
}
253+
}
254+
}
255+
else {
256+
certLen[idx] = (word32)currentPt[sz++];
257+
}
258+
sz += certLen[idx];
259+
certLen[idx] = sz; /* update size to contain first sequence */
260+
}
261+
}
262+
263+
/* advance current pointer and update current total size */
264+
if (ret == WS_SUCCESS) {
265+
if (currentSz + sz > certSz) {
266+
WLOG(WS_LOG_CERTMAN, "cert found is too large!");
267+
ret = ASN_PARSE_E;
268+
break;
269+
}
270+
currentSz += sz;
271+
currentPt += sz;
222272
}
223273
}
224274

225275
if (ret == WS_SUCCESS) {
226-
ret = wolfSSL_CertManagerCheckOCSP(cm->cm, (byte*)cert, certSz);
276+
for (idx = certsCount - 1; idx >= 0; idx--) {
277+
WLOG(WS_LOG_CERTMAN, "verifying cert at index %d", idx);
278+
ret = wolfSSL_CertManagerVerifyBuffer(cm->cm, certLoc[idx],
279+
certLen[idx], WOLFSSL_FILETYPE_ASN1);
280+
if (ret == WOLFSSL_SUCCESS) {
281+
ret = WS_SUCCESS;
282+
}
283+
else if (ret == ASN_NO_SIGNER_E) {
284+
WLOG(WS_LOG_CERTMAN, "cert verify: no signer");
285+
ret = WS_CERT_NO_SIGNER_E;
286+
}
287+
else if (ret == ASN_AFTER_DATE_E) {
288+
WLOG(WS_LOG_CERTMAN, "cert verify: expired");
289+
ret = WS_CERT_EXPIRED_E;
290+
}
291+
else if (ret == ASN_SIG_CONFIRM_E) {
292+
WLOG(WS_LOG_CERTMAN, "cert verify: bad sig");
293+
ret = WS_CERT_SIG_CONFIRM_E;
294+
}
295+
else {
296+
WLOG(WS_LOG_CERTMAN, "cert verify: other error (%d)", ret);
297+
ret = WS_CERT_OTHER_E;
298+
}
227299

228-
if (ret == WOLFSSL_SUCCESS) {
229-
ret = WS_SUCCESS;
230-
}
231-
else if (ret == OCSP_CERT_REVOKED) {
232-
WLOG(WS_LOG_CERTMAN, "ocsp lookup: ocsp revoked");
233-
ret = WS_CERT_REVOKED_E;
234-
}
235-
else {
236-
WLOG(WS_LOG_CERTMAN, "ocsp lookup: other error (%d)", ret);
237-
ret = WS_CERT_OTHER_E;
300+
#ifdef HAVE_OCSP
301+
if (ret == WS_SUCCESS) {
302+
ret = wolfSSL_CertManagerCheckOCSP(cm->cm, (byte*)certLoc[idx],
303+
certLen[idx]);
304+
305+
if (ret == WOLFSSL_SUCCESS) {
306+
ret = WS_SUCCESS;
307+
}
308+
else if (ret == OCSP_CERT_REVOKED) {
309+
WLOG(WS_LOG_CERTMAN, "ocsp lookup: ocsp revoked");
310+
ret = WS_CERT_REVOKED_E;
311+
}
312+
else {
313+
WLOG(WS_LOG_CERTMAN, "ocsp lookup: other error (%d)", ret);
314+
ret = WS_CERT_OTHER_E;
315+
}
316+
}
317+
#endif /* HAVE_OCSP */
318+
319+
/* verified successfully, add intermideate as trusted */
320+
if (ret == WS_SUCCESS && idx > 0) {
321+
WLOG(WS_LOG_CERTMAN, "adding intermidiate cert as trusted");
322+
ret = wolfSSH_CERTMAN_LoadRootCA_buffer(cm, certLoc[idx],
323+
certLen[idx]);
324+
}
325+
326+
if (ret != WS_SUCCESS) {
327+
break;
328+
}
238329
}
239330
}
240331

241332
#ifndef WOLFSSH_NO_FPKI
333+
/* FPKI checking on the leaf certificate */
242334
if (ret == WS_SUCCESS) {
243335
DecodedCert decoded;
244336

245-
wc_InitDecodedCert(&decoded, cert, certSz, cm->cm);
337+
wc_InitDecodedCert(&decoded, certLoc[0], certLen[0], cm->cm);
246338
ret = wc_ParseCert(&decoded, WOLFSSL_FILETYPE_ASN1, 0, cm->cm);
247339

248340
if (ret == 0) {
@@ -387,16 +479,20 @@ static int CheckProfile(DecodedCert* cert, int profile)
387479
/* cycle through alt names to check for needed types */
388480
current = cert->altNames;
389481
while (current != NULL) {
482+
#ifdef WOLFSSL_FPKI
390483
if (current->oidSum == FASCN_OID) {
391484
hasFascN = 1;
392485
}
486+
#endif /* WOLFSSL_FPKI */
393487

394488
current = current->next;
395489
}
396490

491+
#ifdef WOLFSSL_FPKI
397492
if (wc_GetUUIDFromCert(cert, uuid, &uuidSz) == 0) {
398493
hasUUID = 1;
399494
}
495+
#endif /* WOLFSSL_FPKI */
400496

401497
/* all must have UUID and worksheet 6 must have FASC-N in addition to
402498
* UUID */

0 commit comments

Comments
 (0)