From 74b73eab2460119dd7d5a3add2a1425c462f54b2 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 29 Nov 2017 14:27:44 +0100 Subject: gnutls_ocsp_resp_list_import2: introduced That is, introduced function to to import multiple OCSP PEM responses into a list. Signed-off-by: Nikos Mavrogiannopoulos --- lib/includes/gnutls/ocsp.h | 7 +++ lib/libgnutls.map | 1 + lib/x509.h | 2 + lib/x509/ocsp.c | 137 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 145 insertions(+), 2 deletions(-) diff --git a/lib/includes/gnutls/ocsp.h b/lib/includes/gnutls/ocsp.h index 996875d780..966e1d5b8c 100644 --- a/lib/includes/gnutls/ocsp.h +++ b/lib/includes/gnutls/ocsp.h @@ -268,6 +268,13 @@ int gnutls_ocsp_resp_verify(gnutls_ocsp_resp_t resp, int gnutls_ocsp_resp_check_crt(gnutls_ocsp_resp_t resp, unsigned int indx, gnutls_x509_crt_t crt); +int +gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, + unsigned int *size, + const gnutls_datum_t *resp_data, + gnutls_x509_crt_fmt_t format, + unsigned int flags); + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 599ef5e89d..d29d650a81 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1213,6 +1213,7 @@ GNUTLS_3_6_xx gnutls_ocsp_status_request_get2; gnutls_ocsp_resp_import2; gnutls_ocsp_resp_export2; + gnutls_ocsp_resp_list_import2; } GNUTLS_3_6_2; GNUTLS_FIPS140_3_4 { diff --git a/lib/x509.h b/lib/x509.h index 4da17761cd..859824056a 100644 --- a/lib/x509.h +++ b/lib/x509.h @@ -30,6 +30,8 @@ int _gnutls_x509_cert_verify_peers(gnutls_session_t session, #define PEM_CERT_SEP2 "-----BEGIN X509 CERTIFICATE" #define PEM_CERT_SEP "-----BEGIN CERTIFICATE" +#define PEM_OCSP_RESPONSE "-----BEGIN OCSP RESPONSE" +#define BARE_PEM_OCSP_RESPONSE "OCSP RESPONSE" #define PEM_CRL_SEP "-----BEGIN X509 CRL" diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c index 68e7820746..9edaa48022 100644 --- a/lib/x509/ocsp.c +++ b/lib/x509/ocsp.c @@ -31,6 +31,7 @@ #include #include "common.h" #include "verify-high.h" +#include "x509.h" #include #include @@ -264,9 +265,10 @@ gnutls_ocsp_resp_import2(gnutls_ocsp_resp_t resp, der.size = data->size; if (fmt == GNUTLS_X509_FMT_PEM) { - ret = gnutls_pem_base64_decode2("OCSP RESPONSE", data, &der); - if (ret < 0) + ret = gnutls_pem_base64_decode2(BARE_PEM_OCSP_RESPONSE, data, &der); + if (ret < 0) { return gnutls_assert_val(ret); + } } if (resp->init != 0) { @@ -2410,3 +2412,134 @@ gnutls_ocsp_resp_verify(gnutls_ocsp_resp_t resp, return rc; } + +/** + * gnutls_x509_ocsp_resp_list_import2: + * @ocsps: Will hold the parsed OCSP response list. + * @size: It will contain the size of the list. + * @resp_data: The PEM encoded OCSP list. + * @format: Must be PEM. + * @flags: must be (0) or an OR'd sequence of gnutls_certificate_import_flags. + * + * This function will convert the given PEM encoded OCSP response list + * to the native gnutls_ocsp_resp_t format. The output will be stored + * in @ocsps which will allocated and initialized. + * + * The OCSP responses should have a header of "OCSP RESPONSE". + * + * To deinitialize responses, you need to deinitialize each %gnutls_ocsp_resp_t + * structure independently, and use gnutls_free() at @ocsps. + * + * In PEM files, when no OCSP responses are detected + * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. + * + * Returns: the number of responses read or a negative error value. + * + * Since: 3.6.xx + **/ +int +gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, + unsigned int *size, + const gnutls_datum_t *resp_data, + gnutls_x509_crt_fmt_t format, + unsigned int flags) +{ + gnutls_ocsp_resp_t resp = NULL; + gnutls_ocsp_resp_t *new_ocsps; + int ret; + unsigned i; + + + if (format == GNUTLS_X509_FMT_PEM) { + /* load multiple responses */ + gnutls_datum_t p = {resp_data->data, resp_data->size}; + + *size = 0; + *ocsps = NULL; + + p.data = memmem(p.data, p.size, PEM_OCSP_RESPONSE, + sizeof(PEM_OCSP_RESPONSE)-1); + if (p.data == NULL) { + ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + goto cleanup; + } + + p.size -= p.data - resp_data->data; + if (p.size <= 0) { + ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + goto cleanup; + } + + do { + ret = gnutls_ocsp_resp_init(&resp); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = gnutls_ocsp_resp_import2(resp, &p, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + new_ocsps = gnutls_realloc(*ocsps, (*size + 1)*sizeof(gnutls_ocsp_resp_t)); + if (new_ocsps == NULL) { + resp = NULL; + gnutls_assert(); + goto fail; + } + + new_ocsps[*size] = resp; + resp = NULL; + (*size)++; + *ocsps = new_ocsps; + + p.data++; + p.size--; + + p.data = memmem(p.data, p.size, PEM_OCSP_RESPONSE, + sizeof(PEM_OCSP_RESPONSE)-1); + if (p.data == NULL) + break; + p.size = resp_data->size - (p.data - resp_data->data); + } while(p.size > 0); + } else { + /* DER: load a single response */ + ret = gnutls_ocsp_resp_init(&resp); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = gnutls_ocsp_resp_import2(resp, resp_data, GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + *ocsps = gnutls_malloc(1*sizeof(gnutls_ocsp_resp_t)); + if (*ocsps == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + (*ocsps)[0] = resp; + resp = NULL; + *size = 1; + } + + ret = 0; + goto cleanup; + + fail: + for (i=0;i<*size;i++) { + gnutls_ocsp_resp_deinit((*ocsps)[i]); + } + gnutls_free(*ocsps); + + cleanup: + if (resp) + gnutls_ocsp_resp_deinit(resp); + return ret; +} -- cgit v1.2.1