1 /* This example code is placed in the public domain. */
10 #include <gnutls/gnutls.h>
11 #include <gnutls/crypto.h>
12 #include <gnutls/ocsp.h>
14 #include <curl/curl.h>
16 #include "read-file.h"
18 size_t get_data (void *buffer
, size_t size
, size_t nmemb
,
20 static gnutls_x509_crt_t
load_cert (const char *cert_file
);
21 static void _response_info (const gnutls_datum_t
* data
);
23 _generate_request (gnutls_datum_t
* rdata
, gnutls_x509_crt_t cert
,
24 gnutls_x509_crt_t issuer
);
26 _verify_response (gnutls_datum_t
* data
, gnutls_x509_crt_t cert
,
27 gnutls_x509_crt_t signer
);
29 /* This program queries an OCSP server.
30 It expects three files. argv[1] containing the certificate to
31 be checked, argv[2] holding the issuer for this certificate,
32 and argv[3] holding a trusted certificate to verify OCSP's response.
33 argv[4] is optional and should hold the server host name.
35 For simplicity the libcurl library is used.
39 main (int argc
, char *argv
[])
41 gnutls_datum_t ud
, tmp
;
44 gnutls_x509_crt_t cert
, issuer
, signer
;
47 struct curl_slist
*headers
= NULL
;
50 const char *cert_file
= argv
[1];
51 const char *issuer_file
= argv
[2];
52 const char *signer_file
= argv
[3];
53 char *hostname
= NULL
;
55 gnutls_global_init ();
60 cert
= load_cert (cert_file
);
61 issuer
= load_cert (issuer_file
);
62 signer
= load_cert (signer_file
);
69 ret
= gnutls_x509_crt_get_authority_info_access (cert
, seq
,
73 if (ret
== GNUTLS_E_UNKNOWN_ALGORITHM
)
75 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
78 "No URI was found in the certificate.\n");
83 fprintf (stderr
, "error: %s\n",
84 gnutls_strerror (ret
));
88 printf ("CA issuers URI: %.*s\n", tmp
.size
, tmp
.data
);
90 hostname
= malloc (tmp
.size
+ 1);
91 memcpy (hostname
, tmp
.data
, tmp
.size
);
92 hostname
[tmp
.size
] = 0;
94 gnutls_free (tmp
.data
);
100 /* Note that the OCSP servers hostname might be available
101 * using gnutls_x509_crt_get_authority_info_access() in the issuer's
104 memset (&ud
, 0, sizeof (ud
));
105 fprintf (stderr
, "Connecting to %s\n", hostname
);
107 _generate_request (&req
, cert
, issuer
);
110 curl_global_init (CURL_GLOBAL_ALL
);
112 handle
= curl_easy_init ();
117 curl_slist_append (headers
,
118 "Content-Type: application/ocsp-request");
120 curl_easy_setopt (handle
, CURLOPT_HTTPHEADER
, headers
);
121 curl_easy_setopt (handle
, CURLOPT_POSTFIELDS
, (void *) req
.data
);
122 curl_easy_setopt (handle
, CURLOPT_POSTFIELDSIZE
, req
.size
);
123 curl_easy_setopt (handle
, CURLOPT_URL
, hostname
);
124 curl_easy_setopt (handle
, CURLOPT_WRITEFUNCTION
, get_data
);
125 curl_easy_setopt (handle
, CURLOPT_WRITEDATA
, &ud
);
127 ret
= curl_easy_perform (handle
);
130 fprintf (stderr
, "curl[%d] error %d\n", __LINE__
, ret
);
134 curl_easy_cleanup (handle
);
137 _response_info (&ud
);
139 v
= _verify_response (&ud
, cert
, signer
);
141 gnutls_x509_crt_deinit (cert
);
142 gnutls_x509_crt_deinit (issuer
);
143 gnutls_x509_crt_deinit (signer
);
144 gnutls_global_deinit ();
150 _response_info (const gnutls_datum_t
* data
)
152 gnutls_ocsp_resp_t resp
;
156 ret
= gnutls_ocsp_resp_init (&resp
);
160 ret
= gnutls_ocsp_resp_import (resp
, data
);
164 ret
= gnutls_ocsp_resp_print (resp
, GNUTLS_OCSP_PRINT_FULL
, &buf
);
168 printf ("%.*s", buf
.size
, buf
.data
);
169 gnutls_free (buf
.data
);
171 gnutls_ocsp_resp_deinit (resp
);
174 static gnutls_x509_crt_t
175 load_cert (const char *cert_file
)
177 gnutls_x509_crt_t crt
;
182 ret
= gnutls_x509_crt_init (&crt
);
186 data
.data
= (void *) read_binary_file (cert_file
, &size
);
191 fprintf (stderr
, "Cannot open file: %s\n", cert_file
);
195 ret
= gnutls_x509_crt_import (crt
, &data
, GNUTLS_X509_FMT_PEM
);
199 fprintf (stderr
, "Cannot import certificate in %s: %s\n",
200 cert_file
, gnutls_strerror (ret
));
208 _generate_request (gnutls_datum_t
* rdata
, gnutls_x509_crt_t cert
,
209 gnutls_x509_crt_t issuer
)
211 gnutls_ocsp_req_t req
;
213 unsigned char noncebuf
[23];
214 gnutls_datum_t nonce
= { noncebuf
, sizeof (noncebuf
) };
216 ret
= gnutls_ocsp_req_init (&req
);
221 ret
= gnutls_ocsp_req_add_cert (req
, GNUTLS_DIG_SHA1
, issuer
, cert
);
225 ret
= gnutls_rnd (GNUTLS_RND_RANDOM
, nonce
.data
, nonce
.size
);
229 ret
= gnutls_ocsp_req_set_nonce (req
, 0, &nonce
);
233 ret
= gnutls_ocsp_req_export (req
, rdata
);
237 gnutls_ocsp_req_deinit (req
);
243 _verify_response (gnutls_datum_t
* data
, gnutls_x509_crt_t cert
,
244 gnutls_x509_crt_t signer
)
246 gnutls_ocsp_resp_t resp
;
250 ret
= gnutls_ocsp_resp_init (&resp
);
254 ret
= gnutls_ocsp_resp_import (resp
, data
);
258 ret
= gnutls_ocsp_resp_check_crt (resp
, 0, cert
);
262 ret
= gnutls_ocsp_resp_verify_direct (resp
, signer
, &verify
, 0);
266 printf ("Verifying OCSP Response: ");
268 printf ("Verification success!\n");
270 printf ("Verification error!\n");
272 if (verify
& GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND
)
273 printf ("Signer cert not found\n");
275 if (verify
& GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR
)
276 printf ("Signer cert keyusage error\n");
278 if (verify
& GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER
)
279 printf ("Signer cert is not trusted\n");
281 if (verify
& GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM
)
282 printf ("Insecure algorithm\n");
284 if (verify
& GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE
)
285 printf ("Signature failure\n");
287 if (verify
& GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED
)
288 printf ("Signer cert not yet activated\n");
290 if (verify
& GNUTLS_OCSP_VERIFY_CERT_EXPIRED
)
291 printf ("Signer cert expired\n");
293 gnutls_ocsp_resp_deinit (resp
);
299 get_data (void *buffer
, size_t size
, size_t nmemb
, void *userp
)
301 gnutls_datum_t
*ud
= userp
;
305 ud
->data
= realloc (ud
->data
, size
+ ud
->size
);
306 if (ud
->data
== NULL
)
308 fprintf (stderr
, "Not enough memory for the request\n");
312 memcpy (&ud
->data
[ud
->size
], buffer
, size
);