From 291e3a0815bc2e4ca79c96558b749cd4337fd351 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 21 Nov 2017 14:59:31 +0100 Subject: ocsp: introduced gnutls_ocsp_resp_import2 and gnutls_ocsp_resp_export2 These allow importing and exporting an OCSP response to PEM format, in addition to DER. Signed-off-by: Nikos Mavrogiannopoulos --- lib/includes/gnutls/ocsp.h | 6 +++ lib/libgnutls.map | 2 + lib/x509/ocsp.c | 102 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 99 insertions(+), 11 deletions(-) diff --git a/lib/includes/gnutls/ocsp.h b/lib/includes/gnutls/ocsp.h index 8ade965dc0..996875d780 100644 --- a/lib/includes/gnutls/ocsp.h +++ b/lib/includes/gnutls/ocsp.h @@ -196,8 +196,14 @@ void gnutls_ocsp_resp_deinit(gnutls_ocsp_resp_t resp); int gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, const gnutls_datum_t * data); +int gnutls_ocsp_resp_import2(gnutls_ocsp_resp_t resp, + const gnutls_datum_t * data, + gnutls_x509_crt_fmt_t fmt); int gnutls_ocsp_resp_export(gnutls_ocsp_resp_t resp, gnutls_datum_t * data); +int gnutls_ocsp_resp_export2(gnutls_ocsp_resp_t resp, + gnutls_datum_t * data, + gnutls_x509_crt_fmt_t fmt); int gnutls_ocsp_resp_print(gnutls_ocsp_resp_t resp, gnutls_ocsp_print_formats_t format, gnutls_datum_t * out); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 2d611a012f..5ef66b7a59 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1207,6 +1207,8 @@ GNUTLS_3_6_xx gnutls_ext_get_current_msg; gnutls_reauth; gnutls_ocsp_status_request_get2; + gnutls_ocsp_resp_import2; + gnutls_ocsp_resp_export2; } GNUTLS_3_6_2; GNUTLS_FIPS140_3_4 { diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c index 08f4c909ec..68e7820746 100644 --- a/lib/x509/ocsp.c +++ b/lib/x509/ocsp.c @@ -228,14 +228,47 @@ gnutls_ocsp_req_import(gnutls_ocsp_req_t req, const gnutls_datum_t * data) int gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, const gnutls_datum_t * data) +{ + return gnutls_ocsp_resp_import2(resp, data, GNUTLS_X509_FMT_DER); +} + +/** + * gnutls_ocsp_resp_import2: + * @resp: The data to store the parsed response. + * @data: DER or PEM encoded OCSP response. + * @fmt: DER or PEM + * + * This function will convert the given OCSP response to + * the native #gnutls_ocsp_resp_t format. It also decodes the Basic + * OCSP Response part, if any. The output will be stored in @resp. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + * + * Since: 3.6.xx + **/ +int +gnutls_ocsp_resp_import2(gnutls_ocsp_resp_t resp, + const gnutls_datum_t *data, + gnutls_x509_crt_fmt_t fmt) { int ret = 0; + gnutls_datum_t der; if (resp == NULL || data == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } + der.data = data->data; + der.size = data->size; + + if (fmt == GNUTLS_X509_FMT_PEM) { + ret = gnutls_pem_base64_decode2("OCSP RESPONSE", data, &der); + if (ret < 0) + return gnutls_assert_val(ret); + } + if (resp->init != 0) { /* Any earlier _asn1_strict_der_decode will modify the ASN.1 structure, so we need to replace it with a fresh @@ -249,7 +282,8 @@ gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, &resp->resp); if (ret != ASN1_SUCCESS) { gnutls_assert(); - return _gnutls_asn2err(ret); + ret = _gnutls_asn2err(ret); + goto cleanup; } ret = asn1_create_element(_gnutls_get_pkix(), @@ -257,7 +291,8 @@ gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, &resp->basicresp); if (ret != ASN1_SUCCESS) { gnutls_assert(); - return _gnutls_asn2err(ret); + ret = _gnutls_asn2err(ret); + goto cleanup; } gnutls_free(resp->der.data); @@ -265,15 +300,18 @@ gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, } resp->init = 1; - ret = _asn1_strict_der_decode(&resp->resp, data->data, data->size, NULL); + ret = _asn1_strict_der_decode(&resp->resp, der.data, der.size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); - return _gnutls_asn2err(ret); + ret = _gnutls_asn2err(ret); + goto cleanup; } if (gnutls_ocsp_resp_get_status(resp) != - GNUTLS_OCSP_RESP_SUCCESSFUL) - return GNUTLS_E_SUCCESS; + GNUTLS_OCSP_RESP_SUCCESSFUL) { + ret = GNUTLS_E_SUCCESS; + goto cleanup; + } ret = _gnutls_x509_read_value(resp->resp, @@ -281,7 +319,7 @@ gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, &resp->response_type_oid); if (ret < 0) { gnutls_assert(); - return ret; + goto cleanup; } #define OCSP_BASIC "1.3.6.1.5.5.7.48.1.1" @@ -294,7 +332,7 @@ gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, "responseBytes.response", &resp->der); if (ret < 0) { gnutls_assert(); - return ret; + goto cleanup; } ret = @@ -302,14 +340,19 @@ gnutls_ocsp_resp_import(gnutls_ocsp_resp_t resp, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); - return _gnutls_asn2err(ret); + ret = _gnutls_asn2err(ret); + goto cleanup; } } else { asn1_delete_structure(&resp->basicresp); resp->basicresp = NULL; } - return GNUTLS_E_SUCCESS; + ret = GNUTLS_E_SUCCESS; +cleanup: + if (der.data != data->data) + gnutls_free(der.data); + return ret; } /** @@ -356,12 +399,49 @@ int gnutls_ocsp_req_export(gnutls_ocsp_req_t req, gnutls_datum_t * data) **/ int gnutls_ocsp_resp_export(gnutls_ocsp_resp_t resp, gnutls_datum_t * data) { + return gnutls_ocsp_resp_export2(resp, data, GNUTLS_X509_FMT_DER); +} + +/** + * gnutls_ocsp_resp_export2: + * @resp: Holds the OCSP response + * @data: newly allocate buffer holding DER or PEM encoded OCSP response + * @fmt: DER or PEM + * + * This function will export the OCSP response to DER or PEM format. + * + * Returns: In case of failure a negative error code will be + * returned, and 0 on success. + * + * Since: 3.6.xx + **/ +int gnutls_ocsp_resp_export2(gnutls_ocsp_resp_t resp, gnutls_datum_t * data, + gnutls_x509_crt_fmt_t fmt) +{ + int ret; + gnutls_datum_t der; + if (resp == NULL || data == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - return _gnutls_x509_get_raw_field(resp->resp, "", data); + ret = _gnutls_x509_get_raw_field(resp->resp, "", &der); + if (ret < 0) + return gnutls_assert_val(ret); + + if (fmt == GNUTLS_X509_FMT_DER) { + data->data = der.data; + data->size = der.size; + return ret; + } else { + ret = gnutls_pem_base64_encode2("OCSP RESPONSE", &der, data); + gnutls_free(der.data); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; + } } /** -- cgit v1.2.1