/src/wolfssl-openssl-api/src/ocsp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ocsp.c |
2 | | * |
3 | | * Copyright (C) 2006-2022 wolfSSL Inc. |
4 | | * |
5 | | * This file is part of wolfSSL. |
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-1335, USA |
20 | | */ |
21 | | |
22 | | |
23 | | /* Name change compatibility layer no longer needs to be included here */ |
24 | | |
25 | | #ifdef HAVE_CONFIG_H |
26 | | #include <config.h> |
27 | | #endif |
28 | | |
29 | | #include <wolfssl/wolfcrypt/settings.h> |
30 | | |
31 | | #ifndef WOLFCRYPT_ONLY |
32 | | #ifdef HAVE_OCSP |
33 | | |
34 | | #include <wolfssl/error-ssl.h> |
35 | | #include <wolfssl/ocsp.h> |
36 | | #include <wolfssl/internal.h> |
37 | | |
38 | | #ifdef NO_INLINE |
39 | | #include <wolfssl/wolfcrypt/misc.h> |
40 | | #else |
41 | | #define WOLFSSL_MISC_INCLUDED |
42 | | #include <wolfcrypt/src/misc.c> |
43 | | #endif |
44 | | |
45 | | |
46 | | int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) |
47 | 0 | { |
48 | 0 | WOLFSSL_ENTER("InitOCSP"); |
49 | |
|
50 | 0 | ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); |
51 | |
|
52 | 0 | if (wc_InitMutex(&ocsp->ocspLock) != 0) |
53 | 0 | return BAD_MUTEX_E; |
54 | | |
55 | 0 | ocsp->cm = cm; |
56 | |
|
57 | 0 | return 0; |
58 | 0 | } |
59 | | |
60 | | |
61 | | static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) |
62 | 0 | { |
63 | 0 | WOLFSSL_ENTER("InitOcspEntry"); |
64 | |
|
65 | 0 | ForceZero(entry, sizeof(OcspEntry)); |
66 | |
|
67 | 0 | XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); |
68 | 0 | XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); |
69 | |
|
70 | 0 | return 0; |
71 | 0 | } |
72 | | |
73 | | |
74 | | static void FreeOcspEntry(OcspEntry* entry, void* heap) |
75 | 0 | { |
76 | 0 | CertStatus *status, *next; |
77 | |
|
78 | 0 | if (entry == NULL || !entry->ownStatus) |
79 | 0 | return; |
80 | | |
81 | 0 | WOLFSSL_ENTER("FreeOcspEntry"); |
82 | |
|
83 | 0 | for (status = entry->status; status; status = next) { |
84 | 0 | next = status->next; |
85 | |
|
86 | 0 | if (status->rawOcspResponse) |
87 | 0 | XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS); |
88 | |
|
89 | 0 | #ifdef OPENSSL_EXTRA |
90 | 0 | if (status->serialInt) { |
91 | 0 | if (status->serialInt->isDynamic) { |
92 | 0 | XFREE(status->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL); |
93 | 0 | } |
94 | 0 | XFREE(status->serialInt, NULL, DYNAMIC_TYPE_OPENSSL); |
95 | 0 | } |
96 | 0 | status->serialInt = NULL; |
97 | 0 | #endif |
98 | |
|
99 | 0 | XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS); |
100 | 0 | } |
101 | |
|
102 | 0 | (void)heap; |
103 | 0 | } |
104 | | |
105 | | |
106 | | void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) |
107 | 0 | { |
108 | 0 | OcspEntry *entry, *next; |
109 | |
|
110 | 0 | WOLFSSL_ENTER("FreeOCSP"); |
111 | |
|
112 | 0 | for (entry = ocsp->ocspList; entry; entry = next) { |
113 | 0 | next = entry->next; |
114 | 0 | FreeOcspEntry(entry, ocsp->cm->heap); |
115 | 0 | XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); |
116 | 0 | } |
117 | |
|
118 | 0 | wc_FreeMutex(&ocsp->ocspLock); |
119 | |
|
120 | 0 | if (dynamic) |
121 | 0 | XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); |
122 | |
|
123 | 0 | } |
124 | | |
125 | | |
126 | | static int xstat2err(int st) |
127 | 0 | { |
128 | 0 | switch (st) { |
129 | 0 | case CERT_GOOD: |
130 | 0 | return 0; |
131 | 0 | case CERT_REVOKED: |
132 | 0 | return OCSP_CERT_REVOKED; |
133 | 0 | default: |
134 | 0 | return OCSP_CERT_UNKNOWN; |
135 | 0 | } |
136 | 0 | } |
137 | | |
138 | | int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl) |
139 | 0 | { |
140 | 0 | int ret = OCSP_LOOKUP_FAIL; |
141 | |
|
142 | 0 | #ifdef WOLFSSL_SMALL_STACK |
143 | 0 | OcspRequest* ocspRequest; |
144 | | #else |
145 | | OcspRequest ocspRequest[1]; |
146 | | #endif |
147 | |
|
148 | 0 | WOLFSSL_ENTER("CheckCertOCSP"); |
149 | | |
150 | |
|
151 | 0 | #ifdef WOLFSSL_SMALL_STACK |
152 | 0 | ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, |
153 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
154 | 0 | if (ocspRequest == NULL) { |
155 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
156 | 0 | return MEMORY_E; |
157 | 0 | } |
158 | 0 | #endif |
159 | | |
160 | 0 | if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, |
161 | 0 | ocsp->cm->heap) == 0) { |
162 | 0 | ocspRequest->ssl = ssl; |
163 | 0 | ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer); |
164 | |
|
165 | 0 | FreeOcspRequest(ocspRequest); |
166 | 0 | } |
167 | |
|
168 | 0 | #ifdef WOLFSSL_SMALL_STACK |
169 | 0 | XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
170 | 0 | #endif |
171 | |
|
172 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", ret); |
173 | 0 | return ret; |
174 | 0 | } |
175 | | int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) |
176 | 0 | { |
177 | 0 | return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL); |
178 | 0 | } |
179 | | |
180 | | static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, |
181 | | OcspEntry** entry) |
182 | 0 | { |
183 | 0 | WOLFSSL_ENTER("GetOcspEntry"); |
184 | |
|
185 | 0 | *entry = NULL; |
186 | |
|
187 | 0 | if (wc_LockMutex(&ocsp->ocspLock) != 0) { |
188 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); |
189 | 0 | return BAD_MUTEX_E; |
190 | 0 | } |
191 | | |
192 | 0 | for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next) |
193 | 0 | if (XMEMCMP((*entry)->issuerHash, request->issuerHash, |
194 | 0 | OCSP_DIGEST_SIZE) == 0 |
195 | 0 | && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash, |
196 | 0 | OCSP_DIGEST_SIZE) == 0) |
197 | 0 | break; |
198 | |
|
199 | 0 | if (*entry == NULL) { |
200 | 0 | *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), |
201 | 0 | ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); |
202 | 0 | if (*entry) { |
203 | 0 | InitOcspEntry(*entry, request); |
204 | 0 | (*entry)->next = ocsp->ocspList; |
205 | 0 | ocsp->ocspList = *entry; |
206 | 0 | } |
207 | 0 | } |
208 | |
|
209 | 0 | wc_UnLockMutex(&ocsp->ocspLock); |
210 | |
|
211 | 0 | return *entry ? 0 : MEMORY_ERROR; |
212 | 0 | } |
213 | | |
214 | | |
215 | | /* Mallocs responseBuffer->buffer and is up to caller to free on success |
216 | | * |
217 | | * Returns OCSP status |
218 | | */ |
219 | | static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, |
220 | | OcspEntry* entry, CertStatus** status, buffer* responseBuffer) |
221 | 0 | { |
222 | 0 | int ret = OCSP_INVALID_STATUS; |
223 | |
|
224 | 0 | WOLFSSL_ENTER("GetOcspStatus"); |
225 | |
|
226 | 0 | *status = NULL; |
227 | |
|
228 | 0 | if (wc_LockMutex(&ocsp->ocspLock) != 0) { |
229 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); |
230 | 0 | return BAD_MUTEX_E; |
231 | 0 | } |
232 | | |
233 | 0 | for (*status = entry->status; *status; *status = (*status)->next) |
234 | 0 | if ((*status)->serialSz == request->serialSz |
235 | 0 | && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz)) |
236 | 0 | break; |
237 | |
|
238 | 0 | if (responseBuffer && *status && !(*status)->rawOcspResponse) { |
239 | | /* force fetching again */ |
240 | 0 | ret = OCSP_INVALID_STATUS; |
241 | 0 | } |
242 | 0 | else if (*status) { |
243 | 0 | #ifndef NO_ASN_TIME |
244 | 0 | if (XVALIDATE_DATE((*status)->thisDate, |
245 | 0 | (*status)->thisDateFormat, BEFORE) |
246 | 0 | && ((*status)->nextDate[0] != 0) |
247 | 0 | && XVALIDATE_DATE((*status)->nextDate, |
248 | 0 | (*status)->nextDateFormat, AFTER)) |
249 | 0 | #endif |
250 | 0 | { |
251 | 0 | ret = xstat2err((*status)->status); |
252 | |
|
253 | 0 | if (responseBuffer) { |
254 | 0 | responseBuffer->buffer = (byte*)XMALLOC( |
255 | 0 | (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
256 | |
|
257 | 0 | if (responseBuffer->buffer) { |
258 | 0 | responseBuffer->length = (*status)->rawOcspResponseSz; |
259 | 0 | XMEMCPY(responseBuffer->buffer, |
260 | 0 | (*status)->rawOcspResponse, |
261 | 0 | (*status)->rawOcspResponseSz); |
262 | 0 | } |
263 | 0 | } |
264 | 0 | } |
265 | 0 | } |
266 | |
|
267 | 0 | wc_UnLockMutex(&ocsp->ocspLock); |
268 | |
|
269 | 0 | return ret; |
270 | 0 | } |
271 | | |
272 | | /* Check that the response for validity. Store result in status. |
273 | | * |
274 | | * ocsp Context object for OCSP status. |
275 | | * response OCSP response message data. |
276 | | * responseSz Length of OCSP response message data. |
277 | | * reponseBuffer Buffer object to return the response with. |
278 | | * status The certificate status object. |
279 | | * entry The OCSP entry for this certificate. |
280 | | * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. |
281 | | */ |
282 | | int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, |
283 | | WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status, |
284 | | OcspEntry *entry, OcspRequest *ocspRequest) |
285 | 0 | { |
286 | 0 | #ifdef WOLFSSL_SMALL_STACK |
287 | 0 | CertStatus* newStatus; |
288 | 0 | OcspEntry* newSingle; |
289 | 0 | OcspResponse* ocspResponse; |
290 | | #else |
291 | | CertStatus newStatus[1]; |
292 | | OcspEntry newSingle[1]; |
293 | | OcspResponse ocspResponse[1]; |
294 | | #endif |
295 | 0 | int ret; |
296 | 0 | int validated = 0; /* ocsp validation flag */ |
297 | |
|
298 | 0 | #ifdef WOLFSSL_SMALL_STACK |
299 | 0 | newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, |
300 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
301 | 0 | newSingle = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, |
302 | 0 | DYNAMIC_TYPE_OCSP_ENTRY); |
303 | 0 | ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, |
304 | 0 | DYNAMIC_TYPE_OCSP_REQUEST); |
305 | |
|
306 | 0 | if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) { |
307 | 0 | if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); |
308 | 0 | if (newSingle) XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
309 | 0 | if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
310 | |
|
311 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
312 | 0 | return MEMORY_E; |
313 | 0 | } |
314 | 0 | #endif |
315 | 0 | InitOcspResponse(ocspResponse, newSingle, newStatus, response, responseSz, |
316 | 0 | ocsp->cm->heap); |
317 | |
|
318 | 0 | ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); |
319 | 0 | if (ret != 0) { |
320 | 0 | ocsp->error = ret; |
321 | 0 | WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error); |
322 | 0 | goto end; |
323 | 0 | } |
324 | | |
325 | 0 | if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { |
326 | 0 | WOLFSSL_MSG("OcspResponse status bad"); |
327 | 0 | goto end; |
328 | 0 | } |
329 | 0 | if (ocspRequest != NULL) { |
330 | 0 | ret = CompareOcspReqResp(ocspRequest, ocspResponse); |
331 | 0 | if (ret != 0) { |
332 | 0 | goto end; |
333 | 0 | } |
334 | 0 | } |
335 | | |
336 | 0 | if (responseBuffer) { |
337 | 0 | responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap, |
338 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
339 | |
|
340 | 0 | if (responseBuffer->buffer) { |
341 | 0 | responseBuffer->length = responseSz; |
342 | 0 | XMEMCPY(responseBuffer->buffer, response, responseSz); |
343 | 0 | } |
344 | 0 | } |
345 | |
|
346 | 0 | ret = xstat2err(ocspResponse->single->status->status); |
347 | 0 | if (ret == 0) { |
348 | 0 | validated = 1; |
349 | 0 | } |
350 | |
|
351 | 0 | if (wc_LockMutex(&ocsp->ocspLock) != 0) { |
352 | 0 | ret = BAD_MUTEX_E; |
353 | 0 | goto end; |
354 | 0 | } |
355 | | |
356 | 0 | if (status != NULL) { |
357 | 0 | if (status->rawOcspResponse) { |
358 | 0 | XFREE(status->rawOcspResponse, ocsp->cm->heap, |
359 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
360 | 0 | } |
361 | | |
362 | | /* Replace existing certificate entry with updated */ |
363 | 0 | newSingle->status->next = status->next; |
364 | 0 | XMEMCPY(status, newSingle->status, sizeof(CertStatus)); |
365 | 0 | } |
366 | 0 | else { |
367 | | /* Save new certificate entry */ |
368 | 0 | status = (CertStatus*)XMALLOC(sizeof(CertStatus), |
369 | 0 | ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); |
370 | 0 | if (status != NULL) { |
371 | 0 | XMEMCPY(status, newSingle->status, sizeof(CertStatus)); |
372 | 0 | status->next = entry->status; |
373 | 0 | entry->status = status; |
374 | 0 | entry->ownStatus = 1; |
375 | 0 | entry->totalStatus++; |
376 | 0 | } |
377 | 0 | } |
378 | |
|
379 | 0 | if (status && responseBuffer && responseBuffer->buffer) { |
380 | 0 | status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, |
381 | 0 | ocsp->cm->heap, |
382 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
383 | |
|
384 | 0 | if (status->rawOcspResponse) { |
385 | 0 | status->rawOcspResponseSz = responseBuffer->length; |
386 | 0 | XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, |
387 | 0 | responseBuffer->length); |
388 | 0 | } |
389 | 0 | } |
390 | |
|
391 | 0 | wc_UnLockMutex(&ocsp->ocspLock); |
392 | |
|
393 | 0 | end: |
394 | 0 | if (ret == 0 && validated == 1) { |
395 | 0 | WOLFSSL_MSG("New OcspResponse validated"); |
396 | 0 | } else if (ret != OCSP_CERT_REVOKED) { |
397 | 0 | ret = OCSP_LOOKUP_FAIL; |
398 | 0 | } |
399 | |
|
400 | 0 | #ifdef WOLFSSL_SMALL_STACK |
401 | 0 | XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); |
402 | 0 | XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
403 | 0 | XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
404 | 0 | #endif |
405 | 0 | return ret; |
406 | 0 | } |
407 | | |
408 | | /* 0 on success */ |
409 | | /* allow user to override the maximum request size at build-time */ |
410 | | #ifndef OCSP_MAX_REQUEST_SZ |
411 | 0 | #define OCSP_MAX_REQUEST_SZ 2048 |
412 | | #endif |
413 | | int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, |
414 | | buffer* responseBuffer) |
415 | 0 | { |
416 | 0 | OcspEntry* entry = NULL; |
417 | 0 | CertStatus* status = NULL; |
418 | 0 | byte* request = NULL; |
419 | 0 | int requestSz = OCSP_MAX_REQUEST_SZ; |
420 | 0 | int responseSz = 0; |
421 | 0 | byte* response = NULL; |
422 | 0 | const char* url = NULL; |
423 | 0 | int urlSz = 0; |
424 | 0 | int ret = -1; |
425 | 0 | WOLFSSL* ssl; |
426 | 0 | void* ioCtx; |
427 | |
|
428 | 0 | WOLFSSL_ENTER("CheckOcspRequest"); |
429 | |
|
430 | 0 | if (ocsp == NULL || ocspRequest == NULL) |
431 | 0 | return BAD_FUNC_ARG; |
432 | | |
433 | 0 | if (responseBuffer) { |
434 | 0 | responseBuffer->buffer = NULL; |
435 | 0 | responseBuffer->length = 0; |
436 | 0 | } |
437 | |
|
438 | 0 | ret = GetOcspEntry(ocsp, ocspRequest, &entry); |
439 | 0 | if (ret != 0) |
440 | 0 | return ret; |
441 | | |
442 | 0 | ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer); |
443 | 0 | if (ret != OCSP_INVALID_STATUS) |
444 | 0 | return ret; |
445 | | |
446 | | /* get SSL and IOCtx */ |
447 | 0 | ssl = (WOLFSSL*)ocspRequest->ssl; |
448 | 0 | ioCtx = (ssl && ssl->ocspIOCtx != NULL) ? |
449 | 0 | ssl->ocspIOCtx : ocsp->cm->ocspIOCtx; |
450 | |
|
451 | 0 | #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) |
452 | 0 | if (ocsp->statusCb != NULL && ssl != NULL) { |
453 | 0 | ret = ocsp->statusCb(ssl, ioCtx); |
454 | 0 | if (ret == 0) { |
455 | 0 | ret = wolfSSL_get_ocsp_response(ssl, &response); |
456 | 0 | ret = CheckOcspResponse(ocsp, response, ret, responseBuffer, status, |
457 | 0 | entry, NULL); |
458 | 0 | if (response != NULL) |
459 | 0 | XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); |
460 | 0 | return ret; |
461 | 0 | } |
462 | 0 | WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error); |
463 | 0 | return OCSP_LOOKUP_FAIL; |
464 | 0 | } |
465 | 0 | #endif |
466 | | |
467 | 0 | if (ocsp->cm->ocspUseOverrideURL) { |
468 | 0 | url = ocsp->cm->ocspOverrideURL; |
469 | 0 | if (url != NULL && url[0] != '\0') |
470 | 0 | urlSz = (int)XSTRLEN(url); |
471 | 0 | else |
472 | 0 | return OCSP_NEED_URL; |
473 | 0 | } |
474 | 0 | else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { |
475 | 0 | url = (const char *)ocspRequest->url; |
476 | 0 | urlSz = ocspRequest->urlSz; |
477 | 0 | } |
478 | 0 | else { |
479 | | /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ |
480 | 0 | WOLFSSL_MSG("Cert has no OCSP URL, assuming CERT_GOOD"); |
481 | 0 | return 0; |
482 | 0 | } |
483 | | |
484 | 0 | request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); |
485 | 0 | if (request == NULL) { |
486 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
487 | 0 | if (responseBuffer) { |
488 | 0 | XFREE(responseBuffer->buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
489 | 0 | responseBuffer->buffer = NULL; |
490 | 0 | } |
491 | 0 | return MEMORY_ERROR; |
492 | 0 | } |
493 | | |
494 | 0 | requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); |
495 | 0 | if (requestSz > 0 && ocsp->cm->ocspIOCb) { |
496 | 0 | responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz, |
497 | 0 | request, requestSz, &response); |
498 | 0 | } |
499 | 0 | if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { |
500 | 0 | ret = OCSP_WANT_READ; |
501 | 0 | } |
502 | |
|
503 | 0 | XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); |
504 | |
|
505 | 0 | if (responseSz >= 0 && response) { |
506 | 0 | ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status, |
507 | 0 | entry, ocspRequest); |
508 | 0 | } |
509 | |
|
510 | 0 | if (response != NULL && ocsp->cm->ocspRespFreeCb) |
511 | 0 | ocsp->cm->ocspRespFreeCb(ioCtx, response); |
512 | | |
513 | | /* Keep responseBuffer in the case of getting to response check. Caller |
514 | | * should free responseBuffer after checking OCSP return value in "ret" */ |
515 | 0 | WOLFSSL_LEAVE("CheckOcspRequest", ret); |
516 | 0 | return ret; |
517 | 0 | } |
518 | | |
519 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ |
520 | | defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY) |
521 | | |
522 | | int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, |
523 | | WOLFSSL_OCSP_CERTID* id, int* status, int* reason, |
524 | | WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, |
525 | | WOLFSSL_ASN1_TIME** nextupd) |
526 | 0 | { |
527 | 0 | WOLFSSL_OCSP_SINGLERESP* single; |
528 | |
|
529 | 0 | if (bs == NULL || id == NULL) |
530 | 0 | return WOLFSSL_FAILURE; |
531 | | |
532 | 0 | single = bs->single; |
533 | 0 | while (single != NULL) { |
534 | 0 | if ((XMEMCMP(single->status->serial, id->status->serial, single->status->serialSz) == 0) |
535 | 0 | && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0) |
536 | 0 | && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) { |
537 | 0 | break; |
538 | 0 | } |
539 | 0 | single = single->next; |
540 | 0 | } |
541 | |
|
542 | 0 | if (single == NULL) |
543 | 0 | return WOLFSSL_FAILURE; |
544 | | |
545 | 0 | if (status != NULL) |
546 | 0 | *status = single->status->status; |
547 | 0 | if (thisupd != NULL) |
548 | 0 | *thisupd = &single->status->thisDateParsed; |
549 | 0 | if (nextupd != NULL) |
550 | 0 | *nextupd = &single->status->nextDateParsed; |
551 | | |
552 | | /* TODO: Not needed for Nginx or httpd */ |
553 | 0 | if (reason != NULL) |
554 | 0 | *reason = 0; |
555 | 0 | if (revtime != NULL) |
556 | 0 | *revtime = NULL; |
557 | |
|
558 | 0 | return WOLFSSL_SUCCESS; |
559 | 0 | } |
560 | | |
561 | | const char *wolfSSL_OCSP_cert_status_str(long s) |
562 | 0 | { |
563 | 0 | switch (s) { |
564 | 0 | case CERT_GOOD: |
565 | 0 | return "good"; |
566 | 0 | case CERT_REVOKED: |
567 | 0 | return "revoked"; |
568 | 0 | case CERT_UNKNOWN: |
569 | 0 | return "unknown"; |
570 | 0 | default: |
571 | 0 | return "(UNKNOWN)"; |
572 | 0 | } |
573 | 0 | } |
574 | | |
575 | | int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, |
576 | | WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) |
577 | 0 | { |
578 | 0 | (void)thisupd; |
579 | 0 | (void)nextupd; |
580 | 0 | (void)sec; |
581 | 0 | (void)maxsec; |
582 | | /* Dates validated in DecodeSingleResponse. */ |
583 | 0 | return WOLFSSL_SUCCESS; |
584 | 0 | } |
585 | | |
586 | | void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) |
587 | 0 | { |
588 | 0 | FreeOcspEntry(certId, NULL); |
589 | 0 | XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); |
590 | 0 | } |
591 | | |
592 | | WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( |
593 | | const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, |
594 | | const WOLFSSL_X509 *issuer) |
595 | 0 | { |
596 | 0 | WOLFSSL_OCSP_CERTID* certId = NULL; |
597 | 0 | CertStatus* certStatus = NULL; |
598 | 0 | WOLFSSL_CERT_MANAGER* cm = NULL; |
599 | 0 | int ret = -1; |
600 | 0 | DerBuffer* derCert = NULL; |
601 | 0 | #ifdef WOLFSSL_SMALL_STACK |
602 | 0 | DecodedCert *cert = NULL; |
603 | | #else |
604 | | DecodedCert cert[1]; |
605 | | #endif |
606 | |
|
607 | 0 | (void)dgst; |
608 | |
|
609 | 0 | cm = wolfSSL_CertManagerNew(); |
610 | 0 | if (cm == NULL |
611 | 0 | || subject == NULL || subject->derCert == NULL |
612 | 0 | || issuer == NULL || issuer->derCert == NULL) |
613 | 0 | goto out; |
614 | | |
615 | 0 | #ifdef WOLFSSL_SMALL_STACK |
616 | 0 | cert = (DecodedCert *)XMALLOC(sizeof(*cert), cm->heap, DYNAMIC_TYPE_DCERT); |
617 | 0 | if (cert == NULL) |
618 | 0 | goto out; |
619 | 0 | #endif |
620 | | |
621 | 0 | ret = AllocDer(&derCert, issuer->derCert->length, |
622 | 0 | issuer->derCert->type, NULL); |
623 | 0 | if (ret == 0) { |
624 | | /* AddCA() frees the buffer. */ |
625 | 0 | XMEMCPY(derCert->buffer, issuer->derCert->buffer, |
626 | 0 | issuer->derCert->length); |
627 | 0 | ret = AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); |
628 | 0 | if (ret != WOLFSSL_SUCCESS) { |
629 | 0 | goto out; |
630 | 0 | } |
631 | 0 | derCert = NULL; |
632 | 0 | } |
633 | | |
634 | 0 | ret = -1; |
635 | |
|
636 | 0 | certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), |
637 | 0 | cm->heap, DYNAMIC_TYPE_OPENSSL); |
638 | 0 | if (certId == NULL) |
639 | 0 | goto out; |
640 | | |
641 | 0 | certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), cm->heap, |
642 | 0 | DYNAMIC_TYPE_OPENSSL); |
643 | 0 | if (certStatus == NULL) |
644 | 0 | goto out; |
645 | | |
646 | 0 | XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); |
647 | 0 | XMEMSET(certStatus, 0, sizeof(CertStatus)); |
648 | |
|
649 | 0 | certId->status = certStatus; |
650 | 0 | certId->ownStatus = 1; |
651 | |
|
652 | 0 | InitDecodedCert(cert, subject->derCert->buffer, |
653 | 0 | subject->derCert->length, NULL); |
654 | 0 | if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { |
655 | 0 | goto out; |
656 | 0 | } |
657 | 0 | else { |
658 | 0 | XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE); |
659 | 0 | XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE); |
660 | 0 | XMEMCPY(certId->status->serial, cert->serial, cert->serialSz); |
661 | 0 | certId->status->serialSz = cert->serialSz; |
662 | 0 | FreeDecodedCert(cert); |
663 | 0 | } |
664 | | |
665 | 0 | ret = 0; |
666 | |
|
667 | 0 | out: |
668 | |
|
669 | 0 | if (ret != 0) { |
670 | 0 | if (derCert != NULL) |
671 | 0 | FreeDer(&derCert); |
672 | 0 | if (certId != NULL) |
673 | 0 | XFREE(certId, cm->heap, DYNAMIC_TYPE_OPENSSL); |
674 | 0 | if (certStatus) |
675 | 0 | XFREE(certStatus, cm->heap, DYNAMIC_TYPE_OPENSSL); |
676 | 0 | return NULL; |
677 | 0 | } |
678 | | |
679 | 0 | #ifdef WOLFSSL_SMALL_STACK |
680 | 0 | if (cert != NULL) |
681 | 0 | XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); |
682 | 0 | #endif |
683 | |
|
684 | 0 | if (cm != NULL) |
685 | 0 | wolfSSL_CertManagerFree(cm); |
686 | |
|
687 | 0 | return certId; |
688 | 0 | } |
689 | | |
690 | | void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) |
691 | 0 | { |
692 | 0 | wolfSSL_OCSP_RESPONSE_free(basicResponse); |
693 | 0 | } |
694 | | |
695 | | /* Signature verified in DecodeBasicOcspResponse. |
696 | | * But no store available to verify certificate. */ |
697 | | int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, |
698 | | WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags) |
699 | 0 | { |
700 | 0 | int ret; |
701 | 0 | #ifdef WOLFSSL_SMALL_STACK |
702 | 0 | DecodedCert *cert = (DecodedCert *) |
703 | 0 | XMALLOC(sizeof(*cert), (st && st->cm) ? st->cm->heap : NULL, |
704 | 0 | DYNAMIC_TYPE_DCERT); |
705 | 0 | if (cert == NULL) |
706 | 0 | return WOLFSSL_FAILURE; |
707 | | #else |
708 | | DecodedCert cert[1]; |
709 | | #endif |
710 | | |
711 | 0 | (void)certs; |
712 | |
|
713 | 0 | if (flags & OCSP_NOVERIFY) { |
714 | 0 | ret = WOLFSSL_SUCCESS; |
715 | 0 | goto out; |
716 | 0 | } |
717 | | |
718 | 0 | #ifdef OPENSSL_EXTRA |
719 | 0 | if (bs->verifyError != OCSP_VERIFY_ERROR_NONE) { |
720 | 0 | ret = WOLFSSL_FAILURE; |
721 | 0 | goto out; |
722 | 0 | } |
723 | 0 | #endif |
724 | | |
725 | 0 | ret = WOLFSSL_SUCCESS; |
726 | 0 | InitDecodedCert(cert, bs->cert, bs->certSz, NULL); |
727 | 0 | if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm) < 0) |
728 | 0 | ret = WOLFSSL_FAILURE; |
729 | 0 | FreeDecodedCert(cert); |
730 | |
|
731 | 0 | out: |
732 | |
|
733 | 0 | #ifdef WOLFSSL_SMALL_STACK |
734 | 0 | XFREE(cert, (st && st->cm) ? st->cm->heap : NULL, DYNAMIC_TYPE_DCERT); |
735 | 0 | #endif |
736 | |
|
737 | 0 | return ret; |
738 | 0 | } |
739 | | |
740 | | void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) |
741 | 0 | { |
742 | 0 | if (response == NULL) |
743 | 0 | return; |
744 | | |
745 | 0 | if (response->single != NULL) { |
746 | 0 | FreeOcspEntry(response->single, NULL); |
747 | 0 | XFREE(response->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
748 | 0 | } |
749 | |
|
750 | 0 | if (response->source != NULL) |
751 | 0 | XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
752 | |
|
753 | 0 | XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
754 | 0 | } |
755 | | |
756 | | #ifndef NO_BIO |
757 | | OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, |
758 | | OcspResponse** response) |
759 | 0 | { |
760 | 0 | byte* data; |
761 | 0 | byte* p; |
762 | 0 | int len; |
763 | 0 | int dataAlloced = 0; |
764 | 0 | OcspResponse* ret = NULL; |
765 | |
|
766 | 0 | if (bio == NULL) |
767 | 0 | return NULL; |
768 | | |
769 | 0 | if (bio->type == WOLFSSL_BIO_MEMORY) { |
770 | 0 | len = wolfSSL_BIO_get_mem_data(bio, &data); |
771 | 0 | if (len <= 0 || data == NULL) { |
772 | 0 | return NULL; |
773 | 0 | } |
774 | 0 | } |
775 | 0 | #ifndef NO_FILESYSTEM |
776 | 0 | else if (bio->type == WOLFSSL_BIO_FILE) { |
777 | 0 | long fcur; |
778 | 0 | long flen; |
779 | |
|
780 | 0 | if (bio->ptr == NULL) |
781 | 0 | return NULL; |
782 | | |
783 | 0 | fcur = XFTELL((XFILE)bio->ptr); |
784 | 0 | if (fcur < 0) |
785 | 0 | return NULL; |
786 | 0 | if(XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0) |
787 | 0 | return NULL; |
788 | 0 | flen = XFTELL((XFILE)bio->ptr); |
789 | 0 | if (flen < 0) |
790 | 0 | return NULL; |
791 | 0 | if (XFSEEK((XFILE)bio->ptr, fcur, SEEK_SET) != 0) |
792 | 0 | return NULL; |
793 | | |
794 | | /* check calculated length */ |
795 | 0 | fcur = flen - fcur; |
796 | 0 | if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0) |
797 | 0 | return NULL; |
798 | | |
799 | 0 | data = (byte*)XMALLOC(fcur, 0, DYNAMIC_TYPE_TMP_BUFFER); |
800 | 0 | if (data == NULL) |
801 | 0 | return NULL; |
802 | 0 | dataAlloced = 1; |
803 | |
|
804 | 0 | len = wolfSSL_BIO_read(bio, (char *)data, (int)flen); |
805 | 0 | } |
806 | 0 | #endif |
807 | 0 | else |
808 | 0 | return NULL; |
809 | | |
810 | 0 | if (len > 0) { |
811 | 0 | p = data; |
812 | 0 | ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, |
813 | 0 | len); |
814 | 0 | } |
815 | |
|
816 | 0 | if (dataAlloced) |
817 | 0 | XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); |
818 | |
|
819 | 0 | return ret; |
820 | 0 | } |
821 | | #endif /* !NO_BIO */ |
822 | | |
823 | | OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, |
824 | | const unsigned char** data, int len) |
825 | 0 | { |
826 | 0 | OcspResponse *resp = NULL; |
827 | 0 | word32 idx = 0; |
828 | 0 | int length = 0; |
829 | |
|
830 | 0 | if (data == NULL) |
831 | 0 | return NULL; |
832 | | |
833 | 0 | if (response != NULL) |
834 | 0 | resp = *response; |
835 | 0 | if (resp == NULL) { |
836 | 0 | resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, |
837 | 0 | DYNAMIC_TYPE_OCSP_REQUEST); |
838 | 0 | if (resp == NULL) |
839 | 0 | return NULL; |
840 | 0 | XMEMSET(resp, 0, sizeof(OcspResponse)); |
841 | 0 | } |
842 | | |
843 | 0 | resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
844 | 0 | if (resp->source == NULL) { |
845 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
846 | 0 | return NULL; |
847 | 0 | } |
848 | 0 | resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, |
849 | 0 | DYNAMIC_TYPE_OCSP_ENTRY); |
850 | 0 | if (resp->single == NULL) { |
851 | 0 | XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
852 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
853 | 0 | return NULL; |
854 | 0 | } |
855 | 0 | XMEMSET(resp->single, 0, sizeof(OcspEntry)); |
856 | 0 | resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, |
857 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
858 | 0 | resp->single->ownStatus = 1; |
859 | 0 | if (resp->single->status == NULL) { |
860 | 0 | XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
861 | 0 | XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
862 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
863 | 0 | return NULL; |
864 | 0 | } |
865 | 0 | XMEMSET(resp->single->status, 0, sizeof(CertStatus)); |
866 | |
|
867 | 0 | XMEMCPY(resp->source, *data, len); |
868 | 0 | resp->maxIdx = len; |
869 | |
|
870 | 0 | if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) { |
871 | 0 | wolfSSL_OCSP_RESPONSE_free(resp); |
872 | 0 | return NULL; |
873 | 0 | } |
874 | | |
875 | 0 | if (GetSequence(*data, &idx, &length, len) >= 0) |
876 | 0 | (*data) += idx + length; |
877 | |
|
878 | 0 | return resp; |
879 | 0 | } |
880 | | |
881 | | int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, |
882 | | unsigned char** data) |
883 | 0 | { |
884 | 0 | if (data == NULL) |
885 | 0 | return response->maxIdx; |
886 | | |
887 | 0 | XMEMCPY(*data, response->source, response->maxIdx); |
888 | 0 | return response->maxIdx; |
889 | 0 | } |
890 | | |
891 | | int wolfSSL_OCSP_response_status(OcspResponse *response) |
892 | 0 | { |
893 | 0 | return response->responseStatus; |
894 | 0 | } |
895 | | |
896 | | const char *wolfSSL_OCSP_response_status_str(long s) |
897 | 0 | { |
898 | 0 | switch (s) { |
899 | 0 | case OCSP_SUCCESSFUL: |
900 | 0 | return "successful"; |
901 | 0 | case OCSP_MALFORMED_REQUEST: |
902 | 0 | return "malformedrequest"; |
903 | 0 | case OCSP_INTERNAL_ERROR: |
904 | 0 | return "internalerror"; |
905 | 0 | case OCSP_TRY_LATER: |
906 | 0 | return "trylater"; |
907 | 0 | case OCSP_SIG_REQUIRED: |
908 | 0 | return "sigrequired"; |
909 | 0 | case OCSP_UNAUTHORIZED: |
910 | 0 | return "unauthorized"; |
911 | 0 | default: |
912 | 0 | return "(UNKNOWN)"; |
913 | 0 | } |
914 | 0 | } |
915 | | |
916 | | WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) |
917 | 0 | { |
918 | 0 | WOLFSSL_OCSP_BASICRESP* bs; |
919 | |
|
920 | 0 | bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, |
921 | 0 | DYNAMIC_TYPE_OCSP_REQUEST); |
922 | 0 | if (bs == NULL) |
923 | 0 | return NULL; |
924 | | |
925 | 0 | XMEMCPY(bs, response, sizeof(OcspResponse)); |
926 | 0 | bs->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, |
927 | 0 | DYNAMIC_TYPE_OCSP_ENTRY); |
928 | 0 | bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
929 | 0 | if (bs->single == NULL || bs->source == NULL) { |
930 | 0 | if (bs->single) XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
931 | 0 | if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
932 | 0 | wolfSSL_OCSP_RESPONSE_free(bs); |
933 | 0 | bs = NULL; |
934 | 0 | } |
935 | 0 | else { |
936 | 0 | XMEMCPY(bs->single, response->single, sizeof(OcspEntry)); |
937 | 0 | XMEMCPY(bs->source, response->source, response->maxIdx); |
938 | 0 | bs->single->ownStatus = 0; |
939 | 0 | } |
940 | 0 | return bs; |
941 | 0 | } |
942 | | |
943 | | OcspRequest* wolfSSL_OCSP_REQUEST_new(void) |
944 | 0 | { |
945 | 0 | OcspRequest* request; |
946 | |
|
947 | 0 | request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, |
948 | 0 | DYNAMIC_TYPE_OPENSSL); |
949 | 0 | if (request != NULL) |
950 | 0 | XMEMSET(request, 0, sizeof(OcspRequest)); |
951 | |
|
952 | 0 | return request; |
953 | 0 | } |
954 | | |
955 | | void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) |
956 | 0 | { |
957 | 0 | FreeOcspRequest(request); |
958 | 0 | XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL); |
959 | 0 | } |
960 | | |
961 | | int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) |
962 | 0 | { |
963 | 0 | int size; |
964 | |
|
965 | 0 | size = EncodeOcspRequest(request, NULL, 0); |
966 | 0 | if (size <= 0 || data == NULL) |
967 | 0 | return size; |
968 | | |
969 | 0 | return EncodeOcspRequest(request, *data, size); |
970 | 0 | } |
971 | | |
972 | | WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, |
973 | | WOLFSSL_OCSP_CERTID *cid) |
974 | 0 | { |
975 | 0 | if (req == NULL || cid == NULL || cid->status == NULL) |
976 | 0 | return NULL; |
977 | | |
978 | 0 | XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE); |
979 | 0 | XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE); |
980 | 0 | if (cid->status->serialSz > req->serialSz) { |
981 | 0 | if (req->serial != NULL) |
982 | 0 | XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); |
983 | 0 | req->serial = (byte*)XMALLOC(cid->status->serialSz, |
984 | 0 | req->heap, DYNAMIC_TYPE_OCSP_REQUEST); |
985 | 0 | if (req->serial == NULL) |
986 | 0 | return NULL; |
987 | 0 | } |
988 | 0 | XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz); |
989 | 0 | req->serialSz = cid->status->serialSz; |
990 | |
|
991 | 0 | return req; |
992 | 0 | } |
993 | | |
994 | | WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id) |
995 | 0 | { |
996 | 0 | WOLFSSL_OCSP_CERTID* certId; |
997 | |
|
998 | 0 | if (id == NULL) |
999 | 0 | return NULL; |
1000 | | |
1001 | 0 | certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), |
1002 | 0 | NULL, DYNAMIC_TYPE_OPENSSL); |
1003 | 0 | if (certId) { |
1004 | 0 | XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID)); |
1005 | 0 | } |
1006 | 0 | return certId; |
1007 | 0 | } |
1008 | | #endif |
1009 | | |
1010 | | #if defined(OPENSSL_ALL) || defined(APACHE_HTTPD) || defined(WOLFSSL_HAPROXY) |
1011 | | #ifndef NO_BIO |
1012 | | int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, |
1013 | | WOLFSSL_OCSP_REQUEST *req) |
1014 | 0 | { |
1015 | 0 | int size = -1; |
1016 | 0 | unsigned char* data = NULL; |
1017 | |
|
1018 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_OCSP_REQUEST_bio"); |
1019 | 0 | if (out == NULL || req == NULL) |
1020 | 0 | return WOLFSSL_FAILURE; |
1021 | | |
1022 | 0 | size = wolfSSL_i2d_OCSP_REQUEST(req, NULL); |
1023 | 0 | if (size > 0) { |
1024 | 0 | data = (unsigned char*) XMALLOC(size, out->heap, |
1025 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
1026 | 0 | } |
1027 | |
|
1028 | 0 | if (data != NULL) { |
1029 | 0 | size = wolfSSL_i2d_OCSP_REQUEST(req, &data); |
1030 | 0 | } |
1031 | |
|
1032 | 0 | if (size <= 0) { |
1033 | 0 | XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1034 | 0 | return WOLFSSL_FAILURE; |
1035 | 0 | } |
1036 | | |
1037 | 0 | if (wolfSSL_BIO_write(out, data, size) == (int)size) { |
1038 | 0 | XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1039 | 0 | return WOLFSSL_SUCCESS; |
1040 | 0 | } |
1041 | | |
1042 | 0 | XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1043 | 0 | return WOLFSSL_FAILURE; |
1044 | 0 | } |
1045 | | #endif /* !NO_BIO */ |
1046 | | |
1047 | | int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data) |
1048 | 0 | { |
1049 | 0 | if (id == NULL || data == NULL) |
1050 | 0 | return WOLFSSL_FAILURE; |
1051 | | |
1052 | 0 | if (*data != NULL) { |
1053 | 0 | XMEMCPY(*data, id->rawCertId, id->rawCertIdSize); |
1054 | 0 | *data = *data + id->rawCertIdSize; |
1055 | 0 | } |
1056 | 0 | else { |
1057 | 0 | *data = (unsigned char*)XMALLOC(id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL); |
1058 | 0 | if (*data == NULL) { |
1059 | 0 | return WOLFSSL_FAILURE; |
1060 | 0 | } |
1061 | 0 | XMEMCPY(*data, id->rawCertId, id->rawCertIdSize); |
1062 | 0 | } |
1063 | | |
1064 | 0 | return id->rawCertIdSize; |
1065 | 0 | } |
1066 | | |
1067 | | const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(const WOLFSSL_OCSP_SINGLERESP *single) |
1068 | 0 | { |
1069 | 0 | return single; |
1070 | 0 | } |
1071 | | |
1072 | | /** |
1073 | | * Compare two WOLFSSL_OCSP_CERTID objects |
1074 | | * @param a |
1075 | | * @param b |
1076 | | * @return 0 on success and when objects have the same id otherwise either |
1077 | | * the id's don't match or an error occurred |
1078 | | */ |
1079 | | int wolfSSL_OCSP_id_cmp(WOLFSSL_OCSP_CERTID *a, WOLFSSL_OCSP_CERTID *b) |
1080 | 0 | { |
1081 | 0 | int ret = 0; |
1082 | 0 | if (a == NULL || b == NULL) |
1083 | 0 | return WOLFSSL_FATAL_ERROR; |
1084 | | |
1085 | 0 | ret = a->hashAlgoOID != b->hashAlgoOID; |
1086 | 0 | if (ret == 0) |
1087 | 0 | ret = XMEMCMP(a->issuerHash, b->issuerHash, OCSP_DIGEST_SIZE); |
1088 | 0 | if (ret == 0) |
1089 | 0 | ret = XMEMCMP(a->issuerKeyHash, b->issuerKeyHash, OCSP_DIGEST_SIZE); |
1090 | 0 | if (ret == 0) { |
1091 | 0 | if (a->status != NULL && b->status != NULL) { |
1092 | 0 | if (a->status->serialSz == b->status->serialSz) |
1093 | 0 | ret = XMEMCMP(a->status->serial, b->status->serial, |
1094 | 0 | a->status->serialSz); |
1095 | 0 | else |
1096 | 0 | ret = -1; |
1097 | 0 | } |
1098 | 0 | else if (a->status != b->status) { |
1099 | | /* If either is not null then return non-zero */ |
1100 | 0 | ret = -1; |
1101 | 0 | } |
1102 | 0 | } |
1103 | 0 | return ret; |
1104 | 0 | } |
1105 | | |
1106 | | int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single, |
1107 | | int *reason, |
1108 | | WOLFSSL_ASN1_TIME **revtime, |
1109 | | WOLFSSL_ASN1_TIME **thisupd, |
1110 | | WOLFSSL_ASN1_TIME **nextupd) |
1111 | 0 | { |
1112 | 0 | if (single == NULL) |
1113 | 0 | return WOLFSSL_FAILURE; |
1114 | | |
1115 | 0 | if (thisupd != NULL) |
1116 | 0 | *thisupd = &single->status->thisDateParsed; |
1117 | 0 | if (nextupd != NULL) |
1118 | 0 | *nextupd = &single->status->nextDateParsed; |
1119 | |
|
1120 | 0 | if (reason != NULL) |
1121 | 0 | *reason = 0; |
1122 | 0 | if (revtime != NULL) |
1123 | 0 | *revtime = NULL; |
1124 | |
|
1125 | 0 | return single->status->status; |
1126 | 0 | } |
1127 | | |
1128 | | int wolfSSL_OCSP_resp_count(WOLFSSL_OCSP_BASICRESP *bs) |
1129 | 0 | { |
1130 | 0 | WOLFSSL_OCSP_SINGLERESP* single; |
1131 | 0 | int count = 0; |
1132 | |
|
1133 | 0 | if (bs == NULL) |
1134 | 0 | return WOLFSSL_FAILURE; |
1135 | | |
1136 | 0 | single = bs->single; |
1137 | 0 | while(single != NULL) |
1138 | 0 | { |
1139 | 0 | ++count; |
1140 | 0 | single = single->next; |
1141 | 0 | } |
1142 | |
|
1143 | 0 | return count; |
1144 | 0 | } |
1145 | | |
1146 | | WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int idx) |
1147 | 0 | { |
1148 | 0 | WOLFSSL_OCSP_SINGLERESP* single; |
1149 | 0 | int currIdx = 0; |
1150 | |
|
1151 | 0 | if (bs == NULL) |
1152 | 0 | return NULL; |
1153 | | |
1154 | 0 | single = bs->single; |
1155 | 0 | while(single != NULL && currIdx != idx) |
1156 | 0 | { |
1157 | 0 | single = single->next; |
1158 | 0 | ++currIdx; |
1159 | 0 | } |
1160 | |
|
1161 | 0 | return single; |
1162 | 0 | } |
1163 | | |
1164 | | #endif /* OPENSSL_ALL || APACHE_HTTPD || WOLFSSL_HAPROXY */ |
1165 | | |
1166 | | #ifdef OPENSSL_EXTRA |
1167 | | #ifndef NO_WOLFSSL_STUB |
1168 | | int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext, |
1169 | | int idx) |
1170 | 0 | { |
1171 | 0 | WOLFSSL_STUB("wolfSSL_OCSP_REQUEST_add_ext"); |
1172 | 0 | (void)req; |
1173 | 0 | (void)ext; |
1174 | 0 | (void)idx; |
1175 | 0 | return WOLFSSL_FATAL_ERROR; |
1176 | 0 | } |
1177 | | #endif |
1178 | | |
1179 | | #ifndef NO_WOLFSSL_STUB |
1180 | | OcspResponse* wolfSSL_OCSP_response_create(int status, |
1181 | | WOLFSSL_OCSP_BASICRESP* bs) |
1182 | 0 | { |
1183 | 0 | WOLFSSL_STUB("wolfSSL_OCSP_response_create"); |
1184 | 0 | (void)status; |
1185 | 0 | (void)bs; |
1186 | 0 | return NULL; |
1187 | 0 | } |
1188 | | #endif |
1189 | | |
1190 | | #ifndef NO_WOLFSSL_STUB |
1191 | | const char* wolfSSL_OCSP_crl_reason_str(long s) |
1192 | 0 | { |
1193 | 0 | WOLFSSL_STUB("wolfSSL_OCSP_crl_reason_str"); |
1194 | 0 | (void)s; |
1195 | 0 | return NULL; |
1196 | 0 | } |
1197 | | #endif |
1198 | | |
1199 | | /* Returns elements of an OCSP_CERTID struct. Currently only supports |
1200 | | * returning the serial number, and returns an error if user requests |
1201 | | * any of name, pmd, and/or keyHash. |
1202 | | * Return 1 on success, 0 on failure */ |
1203 | | int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, |
1204 | | WOLFSSL_ASN1_OBJECT **pmd, WOLFSSL_ASN1_STRING **keyHash, |
1205 | | WOLFSSL_ASN1_INTEGER **serial, WOLFSSL_OCSP_CERTID *cid) |
1206 | 0 | { |
1207 | 0 | int i = 0; |
1208 | 0 | WOLFSSL_ASN1_INTEGER* ser; |
1209 | |
|
1210 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_id_get0_info"); |
1211 | |
|
1212 | 0 | if (cid == NULL) |
1213 | 0 | return 0; |
1214 | | |
1215 | | /* build up ASN1_INTEGER for serial */ |
1216 | 0 | if (serial != NULL) { |
1217 | 0 | ser = wolfSSL_ASN1_INTEGER_new(); |
1218 | 0 | if (ser == NULL) |
1219 | 0 | return 0; |
1220 | | |
1221 | 0 | if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { |
1222 | | /* allocate data buffer, +2 for type and length */ |
1223 | 0 | ser->data = (unsigned char*)XMALLOC(cid->status->serialSz + 2, NULL, |
1224 | 0 | DYNAMIC_TYPE_OPENSSL); |
1225 | 0 | if (ser->data == NULL) { |
1226 | 0 | wolfSSL_ASN1_INTEGER_free(ser); |
1227 | 0 | return 0; |
1228 | 0 | } |
1229 | 0 | ser->dataMax = cid->status->serialSz + 2; |
1230 | 0 | ser->isDynamic = 1; |
1231 | 0 | } else { |
1232 | | /* Use array instead of dynamic memory */ |
1233 | 0 | ser->data = ser->intData; |
1234 | 0 | ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX; |
1235 | 0 | } |
1236 | | |
1237 | | #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) |
1238 | | /* Serial number starts at 0 index of ser->data */ |
1239 | | XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz); |
1240 | | ser->length = cid->status->serialSz; |
1241 | | #else |
1242 | 0 | ser->data[i++] = ASN_INTEGER; |
1243 | 0 | i += SetLength(cid->status->serialSz, ser->data + i); |
1244 | 0 | XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz); |
1245 | 0 | ser->length = i + cid->status->serialSz; |
1246 | 0 | #endif |
1247 | |
|
1248 | 0 | cid->status->serialInt = ser; |
1249 | 0 | *serial = ser; |
1250 | 0 | } |
1251 | | |
1252 | | /* Not needed for Apache, return error if user is requesting */ |
1253 | 0 | if (name != NULL || pmd != NULL || keyHash != NULL) { |
1254 | 0 | if (name != NULL) |
1255 | 0 | *name = NULL; |
1256 | |
|
1257 | 0 | if (pmd != NULL) |
1258 | 0 | *pmd = NULL; |
1259 | |
|
1260 | 0 | if (keyHash != NULL) |
1261 | 0 | *keyHash = NULL; |
1262 | 0 | return 0; |
1263 | 0 | } |
1264 | | |
1265 | 0 | return 1; |
1266 | 0 | } |
1267 | | |
1268 | | int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val, |
1269 | | int sz) |
1270 | 0 | { |
1271 | 0 | WC_RNG rng; |
1272 | |
|
1273 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_request_add1_nonce"); |
1274 | |
|
1275 | 0 | if (req == NULL || sz > MAX_OCSP_NONCE_SZ) { |
1276 | 0 | WOLFSSL_MSG("Bad parameter"); |
1277 | 0 | return WOLFSSL_FAILURE; |
1278 | 0 | } |
1279 | | |
1280 | 0 | if (sz <= 0) |
1281 | 0 | sz = MAX_OCSP_NONCE_SZ; |
1282 | |
|
1283 | 0 | if (val != NULL) { |
1284 | 0 | XMEMCPY(req->nonce, val, sz); |
1285 | 0 | } |
1286 | 0 | else { |
1287 | 0 | if ( |
1288 | 0 | #ifndef HAVE_FIPS |
1289 | 0 | wc_InitRng_ex(&rng, req->heap, INVALID_DEVID) |
1290 | | #else |
1291 | | wc_InitRng(&rng) |
1292 | | #endif |
1293 | 0 | != 0) { |
1294 | 0 | WOLFSSL_MSG("RNG init failed"); |
1295 | 0 | return WOLFSSL_FAILURE; |
1296 | 0 | } |
1297 | 0 | if (wc_RNG_GenerateBlock(&rng, req->nonce, sz) != 0) { |
1298 | 0 | WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); |
1299 | 0 | wc_FreeRng(&rng); |
1300 | 0 | return WOLFSSL_FAILURE; |
1301 | 0 | } |
1302 | 0 | wc_FreeRng(&rng); |
1303 | 0 | } |
1304 | 0 | req->nonceSz = sz; |
1305 | |
|
1306 | 0 | return WOLFSSL_SUCCESS; |
1307 | 0 | } |
1308 | | |
1309 | | /* Returns result of OCSP nonce comparison. Return values: |
1310 | | * 1 - nonces are both present and equal |
1311 | | * 2 - both nonces are absent |
1312 | | * 3 - nonce only present in response |
1313 | | * -1 - nonce only present in request |
1314 | | * 0 - both nonces present and equal |
1315 | | */ |
1316 | | int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs) |
1317 | 0 | { |
1318 | 0 | byte* reqNonce = NULL; |
1319 | 0 | byte* rspNonce = NULL; |
1320 | 0 | int reqNonceSz = 0; |
1321 | 0 | int rspNonceSz = 0; |
1322 | |
|
1323 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_check_nonce"); |
1324 | |
|
1325 | 0 | if (req != NULL) { |
1326 | 0 | reqNonce = req->nonce; |
1327 | 0 | reqNonceSz = req->nonceSz; |
1328 | 0 | } |
1329 | |
|
1330 | 0 | if (bs != NULL) { |
1331 | 0 | rspNonce = bs->nonce; |
1332 | 0 | rspNonceSz = bs->nonceSz; |
1333 | 0 | } |
1334 | | |
1335 | | /* nonce absent in both req and rsp */ |
1336 | 0 | if (reqNonce == NULL && rspNonce == NULL) |
1337 | 0 | return 2; |
1338 | | |
1339 | | /* nonce present in rsp only */ |
1340 | 0 | if (reqNonce == NULL && rspNonce != NULL) |
1341 | 0 | return 3; |
1342 | | |
1343 | | /* nonce present in req only */ |
1344 | 0 | if (reqNonce != NULL && rspNonce == NULL) |
1345 | 0 | return -1; |
1346 | | |
1347 | | /* nonces are present and equal, return 1. Extra NULL check for fixing |
1348 | | scan-build warning. */ |
1349 | 0 | if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) { |
1350 | 0 | if (XMEMCMP(reqNonce, rspNonce, reqNonceSz) == 0) |
1351 | 0 | return 1; |
1352 | 0 | } |
1353 | | |
1354 | | /* nonces are present but not equal */ |
1355 | 0 | return 0; |
1356 | 0 | } |
1357 | | #endif /* OPENSSL_EXTRA */ |
1358 | | |
1359 | | #else /* HAVE_OCSP */ |
1360 | | |
1361 | | |
1362 | | #ifdef _MSC_VER |
1363 | | /* 4206 warning for blank file */ |
1364 | | #pragma warning(disable: 4206) |
1365 | | #endif |
1366 | | |
1367 | | |
1368 | | #endif /* HAVE_OCSP */ |
1369 | | #endif /* WOLFCRYPT_ONLY */ |