ocsp_cl.c 11 KB

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