ocsp_cl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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 (key)
  142. {
  143. if (!X509_check_private_key(signer, key))
  144. {
  145. OCSPerr(OCSP_F_OCSP_REQUEST_SIGN, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
  146. goto err;
  147. }
  148. if (!OCSP_REQUEST_sign(req, key, dgst)) goto err;
  149. }
  150. if (!(flags & OCSP_NOCERTS))
  151. {
  152. if(!OCSP_request_add1_cert(req, signer)) goto err;
  153. for (i = 0; i < sk_X509_num(certs); i++)
  154. {
  155. x = sk_X509_value(certs, i);
  156. if (!OCSP_request_add1_cert(req, x)) goto err;
  157. }
  158. }
  159. return 1;
  160. err:
  161. OCSP_SIGNATURE_free(req->optionalSignature);
  162. req->optionalSignature = NULL;
  163. return 0;
  164. }
  165. /* Get response status */
  166. int OCSP_response_status(OCSP_RESPONSE *resp)
  167. {
  168. return ASN1_ENUMERATED_get(resp->responseStatus);
  169. }
  170. /* Extract basic response from OCSP_RESPONSE or NULL if
  171. * no basic response present.
  172. */
  173. OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp)
  174. {
  175. OCSP_RESPBYTES *rb;
  176. rb = resp->responseBytes;
  177. if (!rb)
  178. {
  179. OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NO_RESPONSE_DATA);
  180. return NULL;
  181. }
  182. if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic)
  183. {
  184. OCSPerr(OCSP_F_OCSP_RESPONSE_GET1_BASIC, OCSP_R_NOT_BASIC_RESPONSE);
  185. return NULL;
  186. }
  187. return ASN1_item_unpack(rb->response, ASN1_ITEM_rptr(OCSP_BASICRESP));
  188. }
  189. /* Return number of OCSP_SINGLERESP reponses present in
  190. * a basic response.
  191. */
  192. int OCSP_resp_count(OCSP_BASICRESP *bs)
  193. {
  194. if (!bs) return -1;
  195. return sk_OCSP_SINGLERESP_num(bs->tbsResponseData->responses);
  196. }
  197. /* Extract an OCSP_SINGLERESP response with a given index */
  198. OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx)
  199. {
  200. if (!bs) return NULL;
  201. return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx);
  202. }
  203. /* Look single response matching a given certificate ID */
  204. int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last)
  205. {
  206. int i;
  207. STACK_OF(OCSP_SINGLERESP) *sresp;
  208. OCSP_SINGLERESP *single;
  209. if (!bs) return -1;
  210. if (last < 0) last = 0;
  211. else last++;
  212. sresp = bs->tbsResponseData->responses;
  213. for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++)
  214. {
  215. single = sk_OCSP_SINGLERESP_value(sresp, i);
  216. if (!OCSP_id_cmp(id, single->certId)) return i;
  217. }
  218. return -1;
  219. }
  220. /* Extract status information from an OCSP_SINGLERESP structure.
  221. * Note: the revtime and reason values are only set if the
  222. * certificate status is revoked. Returns numerical value of
  223. * status.
  224. */
  225. int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
  226. ASN1_GENERALIZEDTIME **revtime,
  227. ASN1_GENERALIZEDTIME **thisupd,
  228. ASN1_GENERALIZEDTIME **nextupd)
  229. {
  230. int ret;
  231. OCSP_CERTSTATUS *cst;
  232. if(!single) return -1;
  233. cst = single->certStatus;
  234. ret = cst->type;
  235. if (ret == V_OCSP_CERTSTATUS_REVOKED)
  236. {
  237. OCSP_REVOKEDINFO *rev = cst->value.revoked;
  238. if (revtime) *revtime = rev->revocationTime;
  239. if (reason)
  240. {
  241. if(rev->revocationReason)
  242. *reason = ASN1_ENUMERATED_get(rev->revocationReason);
  243. else *reason = -1;
  244. }
  245. }
  246. if(thisupd) *thisupd = single->thisUpdate;
  247. if(nextupd) *nextupd = single->nextUpdate;
  248. return ret;
  249. }
  250. /* This function combines the previous ones: look up a certificate ID and
  251. * if found extract status information. Return 0 is successful.
  252. */
  253. int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
  254. int *reason,
  255. ASN1_GENERALIZEDTIME **revtime,
  256. ASN1_GENERALIZEDTIME **thisupd,
  257. ASN1_GENERALIZEDTIME **nextupd)
  258. {
  259. int i;
  260. OCSP_SINGLERESP *single;
  261. i = OCSP_resp_find(bs, id, -1);
  262. /* Maybe check for multiple responses and give an error? */
  263. if(i < 0) return 0;
  264. single = OCSP_resp_get0(bs, i);
  265. i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd);
  266. if(status) *status = i;
  267. return 1;
  268. }
  269. /* Check validity of thisUpdate and nextUpdate fields. It is possible that the request will
  270. * take a few seconds to process and/or the time wont be totally accurate. Therefore to avoid
  271. * rejecting otherwise valid time we allow the times to be within 'nsec' of the current time.
  272. * Also to avoid accepting very old responses without a nextUpdate field an optional maxage
  273. * parameter specifies the maximum age the thisUpdate field can be.
  274. */
  275. int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec)
  276. {
  277. int ret = 1;
  278. time_t t_now, t_tmp;
  279. time(&t_now);
  280. /* Check thisUpdate is valid and not more than nsec in the future */
  281. if (!ASN1_GENERALIZEDTIME_check(thisupd))
  282. {
  283. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_THISUPDATE_FIELD);
  284. ret = 0;
  285. }
  286. else
  287. {
  288. t_tmp = t_now + nsec;
  289. if (X509_cmp_time(thisupd, &t_tmp) > 0)
  290. {
  291. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_NOT_YET_VALID);
  292. ret = 0;
  293. }
  294. /* If maxsec specified check thisUpdate is not more than maxsec in the past */
  295. if (maxsec >= 0)
  296. {
  297. t_tmp = t_now - maxsec;
  298. if (X509_cmp_time(thisupd, &t_tmp) < 0)
  299. {
  300. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_TOO_OLD);
  301. ret = 0;
  302. }
  303. }
  304. }
  305. if (!nextupd) return ret;
  306. /* Check nextUpdate is valid and not more than nsec in the past */
  307. if (!ASN1_GENERALIZEDTIME_check(nextupd))
  308. {
  309. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
  310. ret = 0;
  311. }
  312. else
  313. {
  314. t_tmp = t_now - nsec;
  315. if (X509_cmp_time(nextupd, &t_tmp) < 0)
  316. {
  317. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_STATUS_EXPIRED);
  318. ret = 0;
  319. }
  320. }
  321. /* Also don't allow nextUpdate to precede thisUpdate */
  322. if (ASN1_STRING_cmp(nextupd, thisupd) < 0)
  323. {
  324. OCSPerr(OCSP_F_OCSP_CHECK_VALIDITY, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
  325. ret = 0;
  326. }
  327. return ret;
  328. }