ocsp.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /* ocsp.c
  2. *
  3. * Copyright (C) 2006-2014 wolfSSL Inc.
  4. *
  5. * This file is part of CyaSSL.
  6. *
  7. * CyaSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * CyaSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <cyassl/ctaocrypt/settings.h>
  25. #ifdef HAVE_OCSP
  26. #include <cyassl/error-ssl.h>
  27. #include <cyassl/ocsp.h>
  28. #include <cyassl/internal.h>
  29. int InitOCSP(CYASSL_OCSP* ocsp, CYASSL_CERT_MANAGER* cm)
  30. {
  31. CYASSL_ENTER("InitOCSP");
  32. XMEMSET(ocsp, 0, sizeof(*ocsp));
  33. ocsp->cm = cm;
  34. if (InitMutex(&ocsp->ocspLock) != 0)
  35. return BAD_MUTEX_E;
  36. return 0;
  37. }
  38. static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
  39. {
  40. CYASSL_ENTER("InitOCSP_Entry");
  41. XMEMSET(ocspe, 0, sizeof(*ocspe));
  42. XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
  43. XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
  44. return 0;
  45. }
  46. static void FreeOCSP_Entry(OCSP_Entry* ocspe)
  47. {
  48. CertStatus* tmp = ocspe->status;
  49. CYASSL_ENTER("FreeOCSP_Entry");
  50. while (tmp) {
  51. CertStatus* next = tmp->next;
  52. XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
  53. tmp = next;
  54. }
  55. }
  56. void FreeOCSP(CYASSL_OCSP* ocsp, int dynamic)
  57. {
  58. OCSP_Entry* tmp = ocsp->ocspList;
  59. CYASSL_ENTER("FreeOCSP");
  60. while (tmp) {
  61. OCSP_Entry* next = tmp->next;
  62. FreeOCSP_Entry(tmp);
  63. XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
  64. tmp = next;
  65. }
  66. FreeMutex(&ocsp->ocspLock);
  67. if (dynamic)
  68. XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
  69. }
  70. static int xstat2err(int stat)
  71. {
  72. switch (stat) {
  73. case CERT_GOOD:
  74. return 0;
  75. case CERT_REVOKED:
  76. return OCSP_CERT_REVOKED;
  77. default:
  78. return OCSP_CERT_UNKNOWN;
  79. }
  80. }
  81. int CheckCertOCSP(CYASSL_OCSP* ocsp, DecodedCert* cert)
  82. {
  83. byte* ocspReqBuf = NULL;
  84. int ocspReqSz = 2048;
  85. byte* ocspRespBuf = NULL;
  86. int result = -1;
  87. OCSP_Entry* ocspe;
  88. CertStatus* certStatus = NULL;
  89. const char *url;
  90. int urlSz;
  91. #ifdef CYASSL_SMALL_STACK
  92. CertStatus* newStatus;
  93. OcspRequest* ocspRequest;
  94. OcspResponse* ocspResponse;
  95. #else
  96. CertStatus newStatus[1];
  97. OcspRequest ocspRequest[1];
  98. OcspResponse ocspResponse[1];
  99. #endif
  100. CYASSL_ENTER("CheckCertOCSP");
  101. if (LockMutex(&ocsp->ocspLock) != 0) {
  102. CYASSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
  103. return BAD_MUTEX_E;
  104. }
  105. ocspe = ocsp->ocspList;
  106. while (ocspe) {
  107. if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
  108. && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
  109. SHA_DIGEST_SIZE) == 0)
  110. break;
  111. else
  112. ocspe = ocspe->next;
  113. }
  114. if (ocspe == NULL) {
  115. ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
  116. NULL, DYNAMIC_TYPE_OCSP_ENTRY);
  117. if (ocspe != NULL) {
  118. InitOCSP_Entry(ocspe, cert);
  119. ocspe->next = ocsp->ocspList;
  120. ocsp->ocspList = ocspe;
  121. }
  122. else {
  123. UnLockMutex(&ocsp->ocspLock);
  124. CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
  125. return MEMORY_ERROR;
  126. }
  127. }
  128. else {
  129. certStatus = ocspe->status;
  130. while (certStatus) {
  131. if (certStatus->serialSz == cert->serialSz &&
  132. XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
  133. break;
  134. else
  135. certStatus = certStatus->next;
  136. }
  137. }
  138. if (certStatus != NULL) {
  139. if (!ValidateDate(certStatus->thisDate,
  140. certStatus->thisDateFormat, BEFORE) ||
  141. (certStatus->nextDate[0] == 0) ||
  142. !ValidateDate(certStatus->nextDate,
  143. certStatus->nextDateFormat, AFTER)) {
  144. CYASSL_MSG("\tinvalid status date, looking up cert");
  145. }
  146. else {
  147. result = xstat2err(certStatus->status);
  148. UnLockMutex(&ocsp->ocspLock);
  149. CYASSL_LEAVE("CheckCertOCSP", result);
  150. return result;
  151. }
  152. }
  153. UnLockMutex(&ocsp->ocspLock);
  154. if (ocsp->cm->ocspUseOverrideURL) {
  155. url = ocsp->cm->ocspOverrideURL;
  156. if (url != NULL && url[0] != '\0')
  157. urlSz = (int)XSTRLEN(url);
  158. else
  159. return OCSP_NEED_URL;
  160. }
  161. else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
  162. url = (const char *)cert->extAuthInfo;
  163. urlSz = cert->extAuthInfoSz;
  164. }
  165. else {
  166. /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
  167. return 0;
  168. }
  169. ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
  170. if (ocspReqBuf == NULL) {
  171. CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
  172. return MEMORY_ERROR;
  173. }
  174. #ifdef CYASSL_SMALL_STACK
  175. newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
  176. DYNAMIC_TYPE_TMP_BUFFER);
  177. ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
  178. DYNAMIC_TYPE_TMP_BUFFER);
  179. ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
  180. DYNAMIC_TYPE_TMP_BUFFER);
  181. if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
  182. if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  183. if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  184. if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  185. XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  186. CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
  187. return MEMORY_E;
  188. }
  189. #endif
  190. InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
  191. ocspReqBuf, ocspReqSz);
  192. ocspReqSz = EncodeOcspRequest(ocspRequest);
  193. if (ocsp->cm->ocspIOCb)
  194. result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
  195. ocspReqBuf, ocspReqSz, &ocspRespBuf);
  196. if (result >= 0 && ocspRespBuf) {
  197. XMEMSET(newStatus, 0, sizeof(CertStatus));
  198. InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
  199. OcspResponseDecode(ocspResponse);
  200. if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
  201. result = OCSP_LOOKUP_FAIL;
  202. else {
  203. if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
  204. result = xstat2err(ocspResponse->status->status);
  205. if (LockMutex(&ocsp->ocspLock) != 0)
  206. result = BAD_MUTEX_E;
  207. else {
  208. if (certStatus != NULL)
  209. /* Replace existing certificate entry with updated */
  210. XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
  211. else {
  212. /* Save new certificate entry */
  213. certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
  214. NULL, DYNAMIC_TYPE_OCSP_STATUS);
  215. if (certStatus != NULL) {
  216. XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
  217. certStatus->next = ocspe->status;
  218. ocspe->status = certStatus;
  219. ocspe->totalStatus++;
  220. }
  221. }
  222. UnLockMutex(&ocsp->ocspLock);
  223. }
  224. }
  225. else
  226. result = OCSP_LOOKUP_FAIL;
  227. }
  228. }
  229. else
  230. result = OCSP_LOOKUP_FAIL;
  231. XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
  232. #ifdef CYASSL_SMALL_STACK
  233. XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  234. XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  235. XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  236. #endif
  237. if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
  238. ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
  239. CYASSL_LEAVE("CheckCertOCSP", result);
  240. return result;
  241. }
  242. #else /* HAVE_OCSP */
  243. #ifdef _MSC_VER
  244. /* 4206 warning for blank file */
  245. #pragma warning(disable: 4206)
  246. #endif
  247. #endif /* HAVE_OCSP */