ocsp_cl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /* ocsp_cl.c */
  2. /* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
  3. * project. */
  4. /* History:
  5. This file was transfered to Richard Levitte from CertCo by Kathy
  6. Weinhold in mid-spring 2000 to be included in OpenSSL or released
  7. as a patch kit. */
  8. /* ====================================================================
  9. * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * 2. Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in
  20. * the documentation and/or other materials provided with the
  21. * distribution.
  22. *
  23. * 3. All advertising materials mentioning features or use of this
  24. * software must display the following acknowledgment:
  25. * "This product includes software developed by the OpenSSL Project
  26. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  27. *
  28. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  29. * endorse or promote products derived from this software without
  30. * prior written permission. For written permission, please contact
  31. * openssl-core@openssl.org.
  32. *
  33. * 5. Products derived from this software may not be called "OpenSSL"
  34. * nor may "OpenSSL" appear in their names without prior written
  35. * permission of the OpenSSL Project.
  36. *
  37. * 6. Redistributions of any form whatsoever must retain the following
  38. * acknowledgment:
  39. * "This product includes software developed by the OpenSSL Project
  40. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  41. *
  42. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  43. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  44. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  45. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  46. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  47. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  48. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  49. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  50. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  51. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  52. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  53. * OF THE POSSIBILITY OF SUCH DAMAGE.
  54. * ====================================================================
  55. *
  56. * This product includes cryptographic software written by Eric Young
  57. * (eay@cryptsoft.com). This product includes software written by Tim
  58. * Hudson (tjh@cryptsoft.com).
  59. *
  60. */
  61. #include <stdio.h>
  62. #include <time.h>
  63. #include <cryptlib.h>
  64. #include <openssl/objects.h>
  65. #include <openssl/rand.h>
  66. #include <openssl/x509.h>
  67. #include <openssl/pem.h>
  68. #include <openssl/x509v3.h>
  69. #include <openssl/ocsp.h>
  70. /* Utility functions related to sending OCSP requests and extracting
  71. * relevant information from the response.
  72. */
  73. /* Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ
  74. * pointer: useful if we want to add extensions.
  75. */
  76. OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid)
  77. {
  78. OCSP_ONEREQ *one = NULL;
  79. if (!(one = OCSP_ONEREQ_new())) goto err;
  80. if (one->reqCert) OCSP_CERTID_free(one->reqCert);
  81. one->reqCert = cid;
  82. if (req &&
  83. !sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one))
  84. goto err;
  85. return one;
  86. err:
  87. OCSP_ONEREQ_free(one);
  88. return NULL;
  89. }
  90. /* Set requestorName from an X509_NAME structure */
  91. int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm)
  92. {
  93. GENERAL_NAME *gen;
  94. gen = GENERAL_NAME_new();
  95. if (gen == NULL)
  96. return 0;
  97. if (!X509_NAME_set(&gen->d.directoryName, nm))
  98. {
  99. GENERAL_NAME_free(gen);
  100. return 0;
  101. }
  102. gen->type = GEN_DIRNAME;
  103. if (req->tbsRequest->requestorName)
  104. GENERAL_NAME_free(req->tbsRequest->requestorName);
  105. req->tbsRequest->requestorName = gen;
  106. return 1;
  107. }
  108. /* Add a certificate to an OCSP request */
  109. int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert)
  110. {
  111. OCSP_SIGNATURE *sig;
  112. if (!req->optionalSignature)
  113. req->optionalSignature = OCSP_SIGNATURE_new();
  114. sig = req->optionalSignature;
  115. if (!sig) return 0;
  116. if (!cert) return 1;
  117. if (!sig->certs && !(sig->certs = sk_X509_new_null()))
  118. return 0;
  119. if(!sk_X509_push(sig->certs, cert)) return 0;
  120. CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
  121. return 1;
  122. }
  123. /* Sign an OCSP request set the requestorName to the subjec
  124. * name of an optional signers certificate and include one
  125. * or more optional certificates in the request. Behaves
  126. * like PKCS7_sign().
  127. */
  128. int OCSP_request_sign(OCSP_REQUEST *req,
  129. X509 *signer,
  130. EVP_PKEY *key,
  131. const EVP_MD *dgst,
  132. STACK_OF(X509) *certs,
  133. unsigned long flags)
  134. {
  135. int i;
  136. OCSP_SIGNATURE *sig;
  137. X509 *x;
  138. if (!OCSP_request_set1_name(req, X509_get_subject_name(signer)))
  139. goto err;
  140. if (!(req->optionalSignature = sig = OCSP_SIGNATURE_new())) goto err;
  141. if (!dgst) dgst = EVP_sha1();
  142. if (key)
  143. {
  144. if (!X509_check_private_key(signer, key))
  145. {
  146. OCSPerr(OCSP_F_OCSP_REQUEST_SIGN, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
  147. goto err;
  148. }
  149. if (!OCSP_REQUEST_sign(req, key, dgst)) goto err;
  150. }
  151. if (!(flags & OCSP_NOCERTS))
  152. {
  153. if(!OCSP_request_add1_cert(req, signer)) goto err;
  154. for (i = 0; i < sk_X509_num(certs); i++)
  155. {
  156. x = sk_X509_value(certs, i);
  157. if (!OCSP_request_add1_cert(req, x)) goto err;
  158. }
  159. }
  160. return 1;
  161. err:
  162. OCSP_SIGNATURE_free(req->optionalSignature);
  163. req->optionalSignature = NULL;
  164. return 0;
  165. }
  166. /* Get response status */
  167. int OCSP_response_status(OCSP_RESPONSE *resp)
  168. {
  169. return ASN1_ENUMERATED_get(resp->responseStatus);
  170. }
  171. /* Extract basic response from OCSP_RESPONSE or NULL if
  172. * no basic response present.
  173. */
  174. OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp)
  175. {
  176. OCSP_RESPBYTES *rb;
  177. rb = resp->responseBytes;
  178. if (!rb)
  179. {
  180. OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NO_RESPONSE_DATA);
  181. return NULL;
  182. }
  183. if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic)
  184. {
  185. OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NOT_BASIC_RESPONSE);
  186. return NULL;
  187. }
  188. return ASN1_item_unpack(rb->response, ASN1_ITEM_rptr(OCSP_BASICRESP));
  189. }
  190. /* Return number of OCSP_SINGLERESP reponses present in
  191. * a basic response.
  192. */
  193. int OCSP_resp_count(OCSP_BASICRESP *bs)
  194. {
  195. if (!bs) return -1;
  196. return sk_OCSP_SINGLERESP_num(bs->tbsResponseData->responses);
  197. }
  198. /* Extract an OCSP_SINGLERESP response with a given index */
  199. OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx)
  200. {
  201. if (!bs) return NULL;
  202. return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx);
  203. }
  204. /* Look single response matching a given certificate ID */
  205. int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last)
  206. {
  207. int i;
  208. STACK_OF(OCSP_SINGLERESP) *sresp;
  209. OCSP_SINGLERESP *single;
  210. if (!bs) return -1;
  211. if (last < 0) last = 0;
  212. else last++;
  213. sresp = bs->tbsResponseData->responses;
  214. for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++)
  215. {
  216. single = sk_OCSP_SINGLERESP_value(sresp, i);
  217. if (!OCSP_id_cmp(id, single->certId)) return i;
  218. }
  219. return -1;
  220. }
  221. /* Extract status information from an OCSP_SINGLERESP structure.
  222. * Note: the revtime and reason values are only set if the
  223. * certificate status is revoked. Returns numerical value of
  224. * status.
  225. */
  226. int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
  227. ASN1_GENERALIZEDTIME **revtime,
  228. ASN1_GENERALIZEDTIME **thisupd,
  229. ASN1_GENERALIZEDTIME **nextupd)
  230. {
  231. int ret;
  232. OCSP_CERTSTATUS *cst;
  233. if(!single) return -1;
  234. cst = single->certStatus;
  235. ret = cst->type;
  236. if (ret == V_OCSP_CERTSTATUS_REVOKED)
  237. {
  238. OCSP_REVOKEDINFO *rev = cst->value.revoked;
  239. if (revtime) *revtime = rev->revocationTime;
  240. if (reason)
  241. {
  242. if(rev->revocationReason)
  243. *reason = ASN1_ENUMERATED_get(rev->revocationReason);
  244. else *reason = -1;
  245. }
  246. }
  247. if(thisupd) *thisupd = single->thisUpdate;
  248. if(nextupd) *nextupd = single->nextUpdate;
  249. return ret;
  250. }
  251. /* This function combines the previous ones: look up a certificate ID and
  252. * if found extract status information. Return 0 is successful.
  253. */
  254. int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
  255. int *reason,
  256. ASN1_GENERALIZEDTIME **revtime,
  257. ASN1_GENERALIZEDTIME **thisupd,
  258. ASN1_GENERALIZEDTIME **nextupd)
  259. {
  260. int i;
  261. OCSP_SINGLERESP *single;
  262. i = OCSP_resp_find(bs, id, -1);
  263. /* Maybe check for multiple responses and give an error? */
  264. if(i < 0) return 0;
  265. single = OCSP_resp_get0(bs, i);
  266. i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd);
  267. if(status) *status = i;
  268. return 1;
  269. }
  270. /* Check validity of thisUpdate and nextUpdate fields. It is possible that the request will
  271. * take a few seconds to process and/or the time wont be totally accurate. Therefore to avoid
  272. * rejecting otherwise valid time we allow the times to be within 'nsec' of the current time.
  273. * Also to avoid accepting very old responses without a nextUpdate field an optional maxage
  274. * parameter specifies the maximum age the thisUpdate field can be.
  275. */
  276. int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec)
  277. {
  278. int ret = 1;
  279. time_t t_now, t_tmp;
  280. time(&t_now);
  281. /* Check thisUpdate is valid and not more than nsec in the future */
  282. if (!ASN1_GENERALIZEDTIME_check(thisupd))
  283. {
  284. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_THISUPDATE_FIELD);
  285. ret = 0;
  286. }
  287. else
  288. {
  289. t_tmp = t_now + nsec;
  290. if (X509_cmp_time(thisupd, &t_tmp) > 0)
  291. {
  292. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_NOT_YET_VALID);
  293. ret = 0;
  294. }
  295. /* If maxsec specified check thisUpdate is not more than maxsec in the past */
  296. if (maxsec >= 0)
  297. {
  298. t_tmp = t_now - maxsec;
  299. if (X509_cmp_time(thisupd, &t_tmp) < 0)
  300. {
  301. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_TOO_OLD);
  302. ret = 0;
  303. }
  304. }
  305. }
  306. if (!nextupd) return ret;
  307. /* Check nextUpdate is valid and not more than nsec in the past */
  308. if (!ASN1_GENERALIZEDTIME_check(nextupd))
  309. {
  310. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
  311. ret = 0;
  312. }
  313. else
  314. {
  315. t_tmp = t_now - nsec;
  316. if (X509_cmp_time(nextupd, &t_tmp) < 0)
  317. {
  318. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_EXPIRED);
  319. ret = 0;
  320. }
  321. }
  322. /* Also don't allow nextUpdate to precede thisUpdate */
  323. if (ASN1_STRING_cmp(nextupd, thisupd) < 0)
  324. {
  325. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
  326. ret = 0;
  327. }
  328. return ret;
  329. }