]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/src/ocsp.c
Update WolfSSL library to the latest version.
[freertos] / FreeRTOS-Plus / Source / WolfSSL / src / ocsp.c
1 /* ocsp.c
2  *
3  * Copyright (C) 2006-2015 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL. (formerly known as CyaSSL)
6  *
7  * wolfSSL 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  * wolfSSL 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
22   /* Name change compatibility layer no longer needs to be included here */
23
24 #ifdef HAVE_CONFIG_H
25     #include <config.h>
26 #endif
27
28 #include <wolfssl/wolfcrypt/settings.h>
29
30 #ifdef HAVE_OCSP
31
32 #include <wolfssl/error-ssl.h>
33 #include <wolfssl/ocsp.h>
34 #include <wolfssl/internal.h>
35
36
37 int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
38 {
39     WOLFSSL_ENTER("InitOCSP");
40     XMEMSET(ocsp, 0, sizeof(*ocsp));
41     ocsp->cm = cm;
42     if (InitMutex(&ocsp->ocspLock) != 0)
43         return BAD_MUTEX_E;
44
45     return 0;
46 }
47
48
49 static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
50 {
51     WOLFSSL_ENTER("InitOCSP_Entry");
52
53     XMEMSET(ocspe, 0, sizeof(*ocspe));
54     XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
55     XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
56
57     return 0;
58 }
59
60
61 static void FreeOCSP_Entry(OCSP_Entry* ocspe)
62 {
63     CertStatus* tmp = ocspe->status;
64
65     WOLFSSL_ENTER("FreeOCSP_Entry");
66
67     while (tmp) {
68         CertStatus* next = tmp->next;
69         XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
70         tmp = next;
71     }
72 }
73
74
75 void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
76 {
77     OCSP_Entry* tmp = ocsp->ocspList;
78
79     WOLFSSL_ENTER("FreeOCSP");
80
81     while (tmp) {
82         OCSP_Entry* next = tmp->next;
83         FreeOCSP_Entry(tmp);
84         XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
85         tmp = next;
86     }
87
88     FreeMutex(&ocsp->ocspLock);
89     if (dynamic)
90         XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
91 }
92
93
94 static int xstat2err(int stat)
95 {
96     switch (stat) {
97         case CERT_GOOD:
98             return 0;
99         case CERT_REVOKED:
100             return OCSP_CERT_REVOKED;
101         default:
102             return OCSP_CERT_UNKNOWN;
103     }
104 }
105
106
107 int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
108 {
109     byte* ocspReqBuf = NULL;
110     int ocspReqSz = 2048;
111     byte* ocspRespBuf = NULL;
112     int result = -1;
113     OCSP_Entry* ocspe;
114     CertStatus* certStatus = NULL;
115     const char *url;
116     int urlSz;
117 #ifdef WOLFSSL_SMALL_STACK
118     CertStatus* newStatus;
119     OcspRequest* ocspRequest;
120     OcspResponse* ocspResponse;
121 #else
122     CertStatus newStatus[1];
123     OcspRequest ocspRequest[1];
124     OcspResponse ocspResponse[1];
125 #endif
126
127     WOLFSSL_ENTER("CheckCertOCSP");
128
129     if (LockMutex(&ocsp->ocspLock) != 0) {
130         WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
131         return BAD_MUTEX_E;
132     }
133
134     ocspe = ocsp->ocspList;
135     while (ocspe) {
136         if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
137             && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
138                                                         SHA_DIGEST_SIZE) == 0)
139             break;
140         else
141             ocspe = ocspe->next;
142     }
143
144     if (ocspe == NULL) {
145         ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
146                                                 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
147         if (ocspe != NULL) {
148             InitOCSP_Entry(ocspe, cert);
149             ocspe->next = ocsp->ocspList;
150             ocsp->ocspList = ocspe;
151         }
152         else {
153             UnLockMutex(&ocsp->ocspLock);
154             WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
155             return MEMORY_ERROR;
156         }
157     }
158     else {
159         certStatus = ocspe->status;
160         while (certStatus) {
161             if (certStatus->serialSz == cert->serialSz &&
162                  XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
163                 break;
164             else
165                 certStatus = certStatus->next;
166         }
167     }
168
169     if (certStatus != NULL) {
170         if (!ValidateDate(certStatus->thisDate,
171                                         certStatus->thisDateFormat, BEFORE) ||
172             (certStatus->nextDate[0] == 0) ||
173             !ValidateDate(certStatus->nextDate,
174                                         certStatus->nextDateFormat, AFTER)) {
175             WOLFSSL_MSG("\tinvalid status date, looking up cert");
176         }
177         else {
178             result = xstat2err(certStatus->status);
179             UnLockMutex(&ocsp->ocspLock);
180             WOLFSSL_LEAVE("CheckCertOCSP", result);
181             return result;
182         }
183     }
184
185     UnLockMutex(&ocsp->ocspLock);
186
187     if (ocsp->cm->ocspUseOverrideURL) {
188         url = ocsp->cm->ocspOverrideURL;
189         if (url != NULL && url[0] != '\0')
190             urlSz = (int)XSTRLEN(url);
191         else
192             return OCSP_NEED_URL;
193     }
194     else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
195         url = (const char *)cert->extAuthInfo;
196         urlSz = cert->extAuthInfoSz;
197     }
198     else {
199         /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
200         return 0;
201     }
202
203     ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
204     if (ocspReqBuf == NULL) {
205         WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
206         return MEMORY_ERROR;
207     }
208
209 #ifdef WOLFSSL_SMALL_STACK
210     newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
211                                                        DYNAMIC_TYPE_TMP_BUFFER);
212     ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
213                                                        DYNAMIC_TYPE_TMP_BUFFER);
214     ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
215                                                        DYNAMIC_TYPE_TMP_BUFFER);
216
217     if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
218         if (newStatus)    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
219         if (ocspRequest)  XFREE(ocspRequest,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
220         if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
221
222         XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
223
224         WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
225         return MEMORY_E;
226     }
227 #endif
228
229     InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
230                                                          ocspReqBuf, ocspReqSz);
231     ocspReqSz = EncodeOcspRequest(ocspRequest);
232     
233     if (ocsp->cm->ocspIOCb)
234         result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
235                                            ocspReqBuf, ocspReqSz, &ocspRespBuf);
236
237     if (result >= 0 && ocspRespBuf) {
238         XMEMSET(newStatus, 0, sizeof(CertStatus));
239
240         InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
241         OcspResponseDecode(ocspResponse);
242     
243         if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
244             result = OCSP_LOOKUP_FAIL;
245         else {
246             if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
247                 result = xstat2err(ocspResponse->status->status);
248
249                 if (LockMutex(&ocsp->ocspLock) != 0)
250                     result = BAD_MUTEX_E;
251                 else {
252                     if (certStatus != NULL)
253                         /* Replace existing certificate entry with updated */
254                         XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
255                     else {
256                         /* Save new certificate entry */
257                         certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
258                                           NULL, DYNAMIC_TYPE_OCSP_STATUS);
259                         if (certStatus != NULL) {
260                             XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
261                             certStatus->next = ocspe->status;
262                             ocspe->status = certStatus;
263                             ocspe->totalStatus++;
264                         }
265                     }
266
267                     UnLockMutex(&ocsp->ocspLock);
268                 }
269             }
270             else
271                 result = OCSP_LOOKUP_FAIL;
272         }
273     }
274     else
275         result = OCSP_LOOKUP_FAIL;
276
277     XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
278
279 #ifdef WOLFSSL_SMALL_STACK
280     XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
281     XFREE(ocspRequest,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
282     XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
283 #endif
284
285     if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
286         ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
287
288     WOLFSSL_LEAVE("CheckCertOCSP", result);
289     return result;
290 }
291
292
293 #else /* HAVE_OCSP */
294
295
296 #ifdef _MSC_VER
297     /* 4206 warning for blank file */
298     #pragma warning(disable: 4206)
299 #endif
300
301
302 #endif /* HAVE_OCSP */
303