From 585c40095a3a92e058c5d1d61137232f17f72195 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 11:32:15 +0100 Subject: [PATCH 1/9] x509: Correctly handle missing responder ID when parsing OCSP response errors The has_issuer() and issued_by() methods relied on it to be defined, so if the OCSP response wasn't successful (i.e. OCSP status indicates an error and no OCSP response is parsed), a null-pointer dereference was caused if the caller checked if the OCSP response was issued by a specific certificate. That's a side-effect of the referenced commit. Previously, error codes caused the OCSP response to not get parsed successfully, which technically wasn't correct as it's well formed and successfully parsed, it's just indicating an error state. Fixes: 00ab8d62c089 ("x509: Support generation of OCSP responses") --- src/libstrongswan/plugins/x509/x509_ocsp_response.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index 3badf36b9..89249c113 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -878,7 +878,11 @@ METHOD(certificate_t, get_issuer, identification_t*, METHOD(certificate_t, has_issuer, id_match_t, private_x509_ocsp_response_t *this, identification_t *issuer) { - return this->responderId->matches(this->responderId, issuer); + if (this->responderId) + { + return this->responderId->matches(this->responderId, issuer); + } + return ID_MATCH_NONE; } METHOD(certificate_t, issued_by, bool, @@ -889,7 +893,7 @@ METHOD(certificate_t, issued_by, bool, bool valid; x509_t *x509 = (x509_t*)issuer; - if (issuer->get_type(issuer) != CERT_X509) + if (issuer->get_type(issuer) != CERT_X509 || !this->responderId) { return FALSE; } From e7a58f46f97583a532b481bb1805aeb5208af565 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 16:52:55 +0100 Subject: [PATCH 2/9] x509: Correctly parse responderId as ASN.1 CHOICE in OCSP response The two OPTs that were used previously allowed to omit it completely (hence the fallback to ID_ANY), but that's invalid, so it's better to fail parsing. --- .../plugins/x509/x509_ocsp_response.c | 85 +++++++++---------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index 89249c113..a47bcc367 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -612,49 +612,49 @@ static bool build_basicOCSPResponse(private_x509_ocsp_response_t *this, * ASN.1 definition of basicResponse */ static const asn1Object_t basicResponseObjects[] = { - { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE | - ASN1_DEF }, /* 2 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */ - { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */ - { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */ - { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */ - { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ - { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */ - { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 16 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */ - { 3, "end loop", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */ - { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */ - { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */ - { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */ - { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } + { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE|ASN1_DEF }, /* 2 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ + { 2, "responderId", ASN1_EOC, ASN1_CHOICE }, /* 4 */ + { 3, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 5 */ + { 4, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ + { 3, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 7 */ + { 3, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 8 */ + { 4, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ + { 3, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 10 */ + { 2, "end choices", ASN1_EOC, ASN1_END|ASN1_CHOICE }, /* 11 */ + { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 12 */ + { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 13 */ + { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 14 */ + { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 15 */ + { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 16 */ + { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 17 */ + { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | ASN1_DEF }, /* 18 */ + { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 19 */ + { 3, "end loop", ASN1_EOC, ASN1_END }, /* 20 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 21 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 22 */ + { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 23 */ + { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 24 */ + { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 25 */ + { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 26 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 27 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 28 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } }; #define BASIC_RESPONSE_TBS_DATA 1 #define BASIC_RESPONSE_VERSION 3 -#define BASIC_RESPONSE_ID_BY_NAME 5 -#define BASIC_RESPONSE_ID_BY_KEY 8 -#define BASIC_RESPONSE_PRODUCED_AT 10 -#define BASIC_RESPONSE_RESPONSES 11 -#define BASIC_RESPONSE_EXT_ID 15 -#define BASIC_RESPONSE_CRITICAL 16 -#define BASIC_RESPONSE_EXT_VALUE 17 -#define BASIC_RESPONSE_ALGORITHM 20 -#define BASIC_RESPONSE_SIGNATURE 21 -#define BASIC_RESPONSE_CERTIFICATE 24 +#define BASIC_RESPONSE_ID_BY_NAME 6 +#define BASIC_RESPONSE_ID_BY_KEY 9 +#define BASIC_RESPONSE_PRODUCED_AT 12 +#define BASIC_RESPONSE_RESPONSES 13 +#define BASIC_RESPONSE_EXT_ID 17 +#define BASIC_RESPONSE_CRITICAL 18 +#define BASIC_RESPONSE_EXT_VALUE 19 +#define BASIC_RESPONSE_ALGORITHM 22 +#define BASIC_RESPONSE_SIGNATURE 23 +#define BASIC_RESPONSE_CERTIFICATE 26 /** * Parse a basicOCSPResponse @@ -756,11 +756,6 @@ end: parser->destroy(parser); if (success) { - if (!this->responderId) - { - this->responderId = identification_create_from_encoding(ID_ANY, - chunk_empty); - } success = parse_responses(this, responses, responses_level); } return success; From b3e66aca5c4af3721489ff7d934d90bc5108e12b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 17:50:02 +0100 Subject: [PATCH 3/9] x509: Add getter for status of OCSP responses --- src/libstrongswan/credentials/certificates/ocsp_response.h | 7 +++++++ src/libstrongswan/plugins/x509/x509_ocsp_response.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/libstrongswan/credentials/certificates/ocsp_response.h b/src/libstrongswan/credentials/certificates/ocsp_response.h index 6f97a3e7a..66dd74ad6 100644 --- a/src/libstrongswan/credentials/certificates/ocsp_response.h +++ b/src/libstrongswan/credentials/certificates/ocsp_response.h @@ -56,6 +56,13 @@ struct ocsp_response_t { */ certificate_t certificate; + /** + * Get general status of this OCSP response. + * + * @return OCSP status + */ + ocsp_status_t (*get_ocsp_status)(ocsp_response_t *this); + /** * Get the nonce received with this OCSP response. * diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index a47bcc367..245b3fac3 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -263,6 +263,12 @@ METHOD(ocsp_response_t, create_response_enumerator, enumerator_t*, filter, NULL, NULL); } +METHOD(ocsp_response_t, get_ocsp_status, ocsp_status_t, + private_x509_ocsp_response_t *this) +{ + return this->ocsp_status; +} + METHOD(ocsp_response_t, get_nonce, chunk_t, private_x509_ocsp_response_t *this) { @@ -1049,6 +1055,7 @@ static private_x509_ocsp_response_t *create_empty() .get_ref = _get_ref, .destroy = _destroy, }, + .get_ocsp_status = _get_ocsp_status, .get_nonce = _get_nonce, .get_status = _get_status, .create_cert_enumerator = _create_cert_enumerator, From 6d345b3dde76489a7012bd1df4d961d820eeec2a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 17:51:57 +0100 Subject: [PATCH 4/9] revocation: Reject OCSP error responses Otherwise, there is lengthy code that tries to validate such responses, even though they don't contain any signatures. --- .../plugins/revocation/revocation_validator.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c index a4e16dffe..4bf2cfb5c 100644 --- a/src/libstrongswan/plugins/revocation/revocation_validator.c +++ b/src/libstrongswan/plugins/revocation/revocation_validator.c @@ -121,8 +121,14 @@ static certificate_t *fetch_ocsp(char *url, certificate_t *subject, request->destroy(request); return NULL; } - ocsp_request = (ocsp_request_t*)request; ocsp_response = (ocsp_response_t*)response; + if (ocsp_response->get_ocsp_status(ocsp_response) != OCSP_SUCCESSFUL) + { + response->destroy(response); + request->destroy(request); + return NULL; + } + ocsp_request = (ocsp_request_t*)request; if (ocsp_response->get_nonce(ocsp_response).len && !chunk_equals_const(ocsp_request->get_nonce(ocsp_request), ocsp_response->get_nonce(ocsp_response))) From 05a1f5b9c596b7cba1fdd8ecbedbdbe81a693103 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 17:53:41 +0100 Subject: [PATCH 5/9] certificate-printer: Add some output for empty OCSP responses --- .../credentials/certificates/certificate_printer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstrongswan/credentials/certificates/certificate_printer.c b/src/libstrongswan/credentials/certificates/certificate_printer.c index 2e6a9d61c..937e4a1e7 100644 --- a/src/libstrongswan/credentials/certificates/certificate_printer.c +++ b/src/libstrongswan/credentials/certificates/certificate_printer.c @@ -558,6 +558,11 @@ static void print_ocsp_response(private_certificate_printer_t *this, fprintf(f, "\n"); } enumerator->destroy(enumerator); + + if (first) + { + fprintf(f, "(none)\n"); + } } } From 945be4ece57d92d9c3011efbdf9f27dd60279bc1 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 17:54:40 +0100 Subject: [PATCH 6/9] pki: Generate internal error OCSP response if no signer certificate is found That can happen if a request is sent to the wrong OCSP server. --- src/pki/commands/ocsp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pki/commands/ocsp.c b/src/pki/commands/ocsp.c index 81e732cf4..85ab67338 100644 --- a/src/pki/commands/ocsp.c +++ b/src/pki/commands/ocsp.c @@ -528,6 +528,11 @@ gen: ocsp_status = OCSP_INTERNALERROR; } } + else + { + DBG1(DBG_APP, "no signer certificate found"); + ocsp_status = OCSP_INTERNALERROR; + } DBG1(DBG_APP, "ocspResponseStatus: %N", ocsp_status_names, ocsp_status); enumerator = responses->create_enumerator(responses); From f3af1704d94ed1db5277151d17e0d2661970d3a8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 18:10:08 +0100 Subject: [PATCH 7/9] x509: Make length of nonces in OCSP requests configurable Some servers might not support a length of 32 and return a malformed request error. Lowering the value to the previous default of 16 could help in that case. --- conf/options/charon.opt | 7 +++++++ src/libstrongswan/plugins/x509/x509_ocsp_request.c | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/conf/options/charon.opt b/conf/options/charon.opt index e07f1dd85..369a11df5 100644 --- a/conf/options/charon.opt +++ b/conf/options/charon.opt @@ -302,6 +302,13 @@ charon.nbns1 charon.nbns2 WINS servers assigned to peer via configuration payload (CP). +charon.ocsp_nonce_len = 32 + Length of nonces in OCSP requests (1-32). + + Length of nonces in OCSP requests. According to RFC 8954, valid values are + between 1 and 32, with new clients required to use 32. Some servers might + not support that so lowering the value to e.g. 16 might be necessary. + charon.port = 500 UDP port used locally. If set to 0 a random port will be allocated. diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index 4f0362967..d04085979 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -205,9 +205,13 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this) static chunk_t build_nonce(private_x509_ocsp_request_t *this) { rng_t *rng; + int nonce_len; + + nonce_len = lib->settings->get_int(lib->settings, "%s.ocsp_nonce_len", + NONCE_LEN, lib->ns); rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!rng || !rng->allocate_bytes(rng, NONCE_LEN, &this->nonce)) + if (!rng || !rng->allocate_bytes(rng, max(1, nonce_len), &this->nonce)) { DBG1(DBG_LIB, "failed to create RNG"); DESTROY_IF(rng); From ebf5afcefa91403b38aeb8de87ed2967b65f631c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 23 Nov 2023 18:40:44 +0100 Subject: [PATCH 8/9] fuzz: Add fuzzing targets for OCSP requests/responses --- fuzz/.gitignore | 2 ++ fuzz/Makefile.am | 9 ++++++++- fuzz/fuzz_ocsp_req.c | 41 +++++++++++++++++++++++++++++++++++++++++ fuzz/fuzz_ocsp_rsp.c | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 fuzz/fuzz_ocsp_req.c create mode 100644 fuzz/fuzz_ocsp_rsp.c diff --git a/fuzz/.gitignore b/fuzz/.gitignore index 0927874fb..99ebd93bc 100644 --- a/fuzz/.gitignore +++ b/fuzz/.gitignore @@ -1,5 +1,7 @@ fuzz_certs fuzz_crls +fuzz_ocsp_req +fuzz_ocsp_rsp fuzz_ids fuzz_pa_tnc fuzz_pb_tnc diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index e2254c1e8..c2d534380 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -25,7 +25,8 @@ pb_tnc_ldflags = \ $(top_builddir)/src/libtncif/.libs/libtncif.a \ $(fuzz_ldflags) -FUZZ_TARGETS=fuzz_certs fuzz_crls fuzz_ids fuzz_pa_tnc fuzz_pb_tnc +FUZZ_TARGETS=fuzz_certs fuzz_crls fuzz_ocsp_req fuzz_ocsp_rsp \ + fuzz_ids fuzz_pa_tnc fuzz_pb_tnc all-local: $(FUZZ_TARGETS) @@ -37,6 +38,12 @@ fuzz_certs: fuzz_certs.c ${libfuzzer} fuzz_crls: fuzz_crls.c ${libfuzzer} $(CC) $(AM_CPPFLAGS) $(CFLAGS) -o $@ $< $(fuzz_ldflags) +fuzz_ocsp_req: fuzz_ocsp_req.c ${libfuzzer} + $(CC) $(AM_CPPFLAGS) $(CFLAGS) -o $@ $< $(fuzz_ldflags) + +fuzz_ocsp_rsp: fuzz_ocsp_rsp.c ${libfuzzer} + $(CC) $(AM_CPPFLAGS) $(CFLAGS) -o $@ $< $(fuzz_ldflags) + fuzz_ids: fuzz_ids.c ${libfuzzer} $(CC) $(AM_CPPFLAGS) $(CFLAGS) -o $@ $< $(fuzz_ldflags) diff --git a/fuzz/fuzz_ocsp_req.c b/fuzz/fuzz_ocsp_req.c new file mode 100644 index 000000000..111ef6365 --- /dev/null +++ b/fuzz/fuzz_ocsp_req.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 Tobias Brunner + * + * Copyright (C) secunet Security Networks AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + certificate_t *cert; + chunk_t chunk; + + dbg_default_set_level(-1); + library_init(NULL, "fuzz_ocsp_req"); + plugin_loader_add_plugindirs(PLUGINDIR, PLUGINS); + if (!lib->plugins->load(lib->plugins, PLUGINS)) + { + return 1; + } + + chunk = chunk_create((u_char*)buf, len); + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, + BUILD_BLOB, chunk, BUILD_END); + DESTROY_IF(cert); + + lib->plugins->unload(lib->plugins); + library_deinit(); + return 0; +} diff --git a/fuzz/fuzz_ocsp_rsp.c b/fuzz/fuzz_ocsp_rsp.c new file mode 100644 index 000000000..6778c53f9 --- /dev/null +++ b/fuzz/fuzz_ocsp_rsp.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 Tobias Brunner + * + * Copyright (C) secunet Security Networks AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) +{ + certificate_t *cert; + chunk_t chunk; + + dbg_default_set_level(-1); + library_init(NULL, "fuzz_ocsp_rsp"); + plugin_loader_add_plugindirs(PLUGINDIR, PLUGINS); + if (!lib->plugins->load(lib->plugins, PLUGINS)) + { + return 1; + } + + chunk = chunk_create((u_char*)buf, len); + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, + BUILD_BLOB, chunk, BUILD_END); + DESTROY_IF(cert); + + lib->plugins->unload(lib->plugins); + library_deinit(); + return 0; +} From 9c4846cdbe61af324f44f7e59a9e209fef112157 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 24 Nov 2023 14:49:24 +0100 Subject: [PATCH 9/9] x509: Make sure the status in OCSP responses has the correct length --- src/libstrongswan/plugins/x509/x509_ocsp_response.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index 245b3fac3..820e4ceba 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -827,6 +827,10 @@ static bool parse_OCSPResponse(private_x509_ocsp_response_t *this) switch (objectID) { case OCSP_RESPONSE_STATUS: + if (object.len != 1) + { + goto end; + } this->ocsp_status = (ocsp_status_t)*object.ptr; switch (this->ocsp_status) {