summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-09-30 18:09:46 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-09-30 18:09:46 +0200
commit7b9d0158f022b8468ea7cd362ef9142889f4ff29 (patch)
treeb51e18b22ea218d20606fd4ddfdc1e4bbfdc0eda /lib
parent52f373cdf26d50e05f5dd49e4ecc8b29fc742535 (diff)
downloadgnutls-7b9d0158f022b8468ea7cd362ef9142889f4ff29.tar.gz
Added gnutls_ocsp_resp_check_crt() to check whether the OCSP
response corresponds to the given certificate.
Diffstat (limited to 'lib')
-rw-r--r--lib/gnutls_errors.c2
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
-rw-r--r--lib/includes/gnutls/ocsp.h4
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/x509/ocsp.c97
5 files changed, 106 insertions, 0 deletions
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 71b6e6acf1..5e8df249e9 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -334,6 +334,8 @@ static const gnutls_error_entry error_algorithms[] = {
GNUTLS_E_PKCS11_REQUESTED_OBJECT_NOT_AVAILBLE, 1),
ERROR_ENTRY (N_("The provided X.509 certificate list is not sorted (in subject to issuer order)"),
GNUTLS_E_CERTIFICATE_LIST_UNSORTED, 1),
+ ERROR_ENTRY (N_("The OCSP response is invalid"),
+ GNUTLS_E_OCSP_RESPONSE_ERROR, 1),
{NULL, NULL, 0, 0}
};
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 773834cedc..355621a370 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1905,6 +1905,8 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
#define GNUTLS_E_X509_UNSUPPORTED_EXTENSION -327
#define GNUTLS_E_SESSION_EOF -328
+#define GNUTLS_E_OCSP_RESPONSE_ERROR -341
+
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/includes/gnutls/ocsp.h b/lib/includes/gnutls/ocsp.h
index db16b70c10..70343a23e9 100644
--- a/lib/includes/gnutls/ocsp.h
+++ b/lib/includes/gnutls/ocsp.h
@@ -249,6 +249,10 @@ extern "C"
unsigned int *verify,
unsigned int flags);
+int
+gnutls_ocsp_resp_check_crt (gnutls_ocsp_resp_t resp,
+ gnutls_x509_crt_t crt);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 1078a07680..f1647335ee 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -790,6 +790,7 @@ GNUTLS_3_0_0 {
gnutls_pk_to_sign;
gnutls_certificate_set_x509_system_trust;
gnutls_session_set_premaster;
+ gnutls_ocsp_resp_check_crt;
} GNUTLS_2_12;
GNUTLS_PRIVATE {
diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c
index 0857e33acf..3aca0f52f7 100644
--- a/lib/x509/ocsp.c
+++ b/lib/x509/ocsp.c
@@ -1275,6 +1275,103 @@ gnutls_ocsp_resp_get_produced (gnutls_ocsp_resp_t resp)
}
/**
+ * gnutls_ocsp_resp_check_crt:
+ * @resp: should contain a #gnutls_ocsp_resp_t structure
+ * @crt: The certificate to check
+ *
+ * This function will check whether the OCSP response
+ * is about the provided certificate.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error code is returned.
+ **/
+int
+gnutls_ocsp_resp_check_crt (gnutls_ocsp_resp_t resp,
+ gnutls_x509_crt_t crt)
+{
+int ret;
+gnutls_digest_algorithm_t digest;
+gnutls_datum_t rdn_hash = {NULL, 0}, rserial = {NULL, 0};
+gnutls_datum_t cserial = {NULL, 0};
+gnutls_datum_t dn = {NULL, 0};
+uint8_t cdn_hash[MAX_HASH_SIZE];
+size_t t, hash_len;
+
+ ret = gnutls_ocsp_resp_get_single (resp, 0, &digest, &rdn_hash, NULL,
+ &rserial, NULL, NULL, NULL, NULL, NULL);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if (rserial.size == 0 || digest == GNUTLS_DIG_UNKNOWN)
+ {
+ ret = gnutls_assert_val(GNUTLS_E_OCSP_RESPONSE_ERROR);
+ goto cleanup;
+ }
+
+ hash_len = _gnutls_hash_get_algo_len(digest);
+ if (hash_len != rdn_hash.size)
+ {
+ ret = gnutls_assert_val(GNUTLS_E_OCSP_RESPONSE_ERROR);
+ goto cleanup;
+ }
+
+ cserial.size = rserial.size;
+ cserial.data = gnutls_malloc(cserial.size);
+ if (cserial.data == NULL)
+ {
+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ goto cleanup;
+ }
+
+ t = cserial.size;
+ ret = gnutls_x509_crt_get_serial(crt, cserial.data, &t);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if (rserial.size != cserial.size || memcmp(cserial.data, rserial.data, rserial.size) != 0)
+ {
+ ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &dn);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = _gnutls_hash_fast( digest, dn.data, dn.size, cdn_hash);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if (memcmp(cdn_hash, rdn_hash.data, hash_len) != 0)
+ {
+ ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ gnutls_free(rdn_hash.data);
+ gnutls_free(rserial.data);
+ gnutls_free(cserial.data);
+ gnutls_free(dn.data);
+
+ return ret;
+}
+
+
+/**
* gnutls_ocsp_resp_get_single:
* @resp: should contain a #gnutls_ocsp_resp_t structure
* @indx: Specifies which extension OID to get. Use (0) to get the first one.