/src/wolfssl-openssl-api/src/ocsp.c
Line | Count | Source |
1 | | /* ocsp.c |
2 | | * |
3 | | * Copyright (C) 2006-2025 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 3 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 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
23 | | |
24 | | /* Name change compatibility layer no longer needs to be included here */ |
25 | | |
26 | | /* |
27 | | * WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK: |
28 | | * Disable looking for an authorized responder in the verification path of |
29 | | * the issuer. This will make the authorized responder only look at the |
30 | | * OCSP response signer and direct issuer. |
31 | | */ |
32 | | |
33 | | #ifndef WOLFCRYPT_ONLY |
34 | | #ifdef HAVE_OCSP |
35 | | |
36 | | #include <wolfssl/error-ssl.h> |
37 | | #include <wolfssl/ocsp.h> |
38 | | #include <wolfssl/internal.h> |
39 | | |
40 | | #ifdef NO_INLINE |
41 | | #include <wolfssl/wolfcrypt/misc.h> |
42 | | #else |
43 | | #define WOLFSSL_MISC_INCLUDED |
44 | | #include <wolfcrypt/src/misc.c> |
45 | | #endif |
46 | | |
47 | | /* Allocates and initializes a WOLFSSL_OCSP object. Returns pointer on success, NULL on failure. */ |
48 | | WOLFSSL_OCSP* wc_NewOCSP(WOLFSSL_CERT_MANAGER* cm) |
49 | 0 | { |
50 | 0 | WOLFSSL_OCSP* ocsp = NULL; |
51 | 0 | ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm ? cm->heap : NULL, DYNAMIC_TYPE_OCSP); |
52 | 0 | if (ocsp == NULL) |
53 | 0 | return NULL; |
54 | 0 | if (InitOCSP(ocsp, cm) != 0) { |
55 | 0 | XFREE(ocsp, cm ? cm->heap : NULL, DYNAMIC_TYPE_OCSP); |
56 | 0 | return NULL; |
57 | 0 | } |
58 | 0 | return ocsp; |
59 | 0 | } |
60 | | |
61 | | /* Frees a WOLFSSL_OCSP object allocated by wc_NewOCSP. */ |
62 | | void wc_FreeOCSP(WOLFSSL_OCSP* ocsp) |
63 | 0 | { |
64 | 0 | if (ocsp) { |
65 | 0 | FreeOCSP(ocsp, 1); |
66 | 0 | } |
67 | 0 | } |
68 | | |
69 | | int wc_CheckCertOcspResponse(WOLFSSL_OCSP *ocsp, DecodedCert *cert, |
70 | | byte *response, int responseSz, void* heap) |
71 | 0 | { |
72 | 0 | int ret = WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E); |
73 | |
|
74 | 0 | #ifdef WOLFSSL_SMALL_STACK |
75 | 0 | OcspRequest* ocspRequest; |
76 | | #else |
77 | | OcspRequest ocspRequest[1]; |
78 | | #endif |
79 | | |
80 | |
|
81 | 0 | #ifdef WOLFSSL_SMALL_STACK |
82 | 0 | ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, |
83 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
84 | 0 | if (ocspRequest == NULL) { |
85 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
86 | 0 | return MEMORY_E; |
87 | 0 | } |
88 | 0 | #endif |
89 | | |
90 | 0 | if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, |
91 | 0 | ocsp->cm->heap) == 0) { |
92 | 0 | ret = CheckOcspResponse(ocsp, response, responseSz, NULL, NULL, NULL, |
93 | 0 | ocspRequest, heap); |
94 | 0 | FreeOcspRequest(ocspRequest); |
95 | 0 | } |
96 | |
|
97 | 0 | #ifdef WOLFSSL_SMALL_STACK |
98 | 0 | XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
99 | 0 | #endif |
100 | |
|
101 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", ret); |
102 | 0 | return ret; |
103 | 0 | } |
104 | | |
105 | | int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) |
106 | 28 | { |
107 | 28 | WOLFSSL_ENTER("InitOCSP"); |
108 | | |
109 | 28 | ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); |
110 | | |
111 | 28 | if (wc_InitMutex(&ocsp->ocspLock) != 0) |
112 | 0 | return BAD_MUTEX_E; |
113 | | |
114 | 28 | ocsp->cm = cm; |
115 | | |
116 | 28 | return 0; |
117 | 28 | } |
118 | | |
119 | | |
120 | | static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) |
121 | 0 | { |
122 | 0 | WOLFSSL_ENTER("InitOcspEntry"); |
123 | |
|
124 | 0 | ForceZero(entry, sizeof(OcspEntry)); |
125 | |
|
126 | 0 | XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); |
127 | 0 | XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); |
128 | |
|
129 | 0 | return 0; |
130 | 0 | } |
131 | | |
132 | | |
133 | | static void FreeOcspEntry(OcspEntry* entry, void* heap) |
134 | 0 | { |
135 | 0 | CertStatus *status, *next; |
136 | |
|
137 | 0 | if (entry == NULL || !entry->ownStatus) |
138 | 0 | return; |
139 | | |
140 | 0 | WOLFSSL_ENTER("FreeOcspEntry"); |
141 | |
|
142 | 0 | for (status = entry->status; status; status = next) { |
143 | 0 | next = status->next; |
144 | |
|
145 | 0 | XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS); |
146 | |
|
147 | 0 | #ifdef OPENSSL_EXTRA |
148 | 0 | if (status->serialInt) { |
149 | 0 | if (status->serialInt->isDynamic) { |
150 | 0 | XFREE(status->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL); |
151 | 0 | } |
152 | 0 | XFREE(status->serialInt, NULL, DYNAMIC_TYPE_OPENSSL); |
153 | 0 | } |
154 | 0 | status->serialInt = NULL; |
155 | 0 | #endif |
156 | |
|
157 | 0 | XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS); |
158 | 0 | } |
159 | |
|
160 | 0 | (void)heap; |
161 | 0 | } |
162 | | |
163 | | |
164 | | void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) |
165 | 0 | { |
166 | 0 | OcspEntry *entry, *next; |
167 | |
|
168 | 0 | WOLFSSL_ENTER("FreeOCSP"); |
169 | |
|
170 | 0 | for (entry = ocsp->ocspList; entry; entry = next) { |
171 | 0 | next = entry->next; |
172 | 0 | FreeOcspEntry(entry, ocsp->cm->heap); |
173 | 0 | XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); |
174 | 0 | } |
175 | |
|
176 | 0 | wc_FreeMutex(&ocsp->ocspLock); |
177 | |
|
178 | 0 | if (dynamic) |
179 | 0 | XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); |
180 | |
|
181 | 0 | } |
182 | | |
183 | | |
184 | | static int xstat2err(int st) |
185 | 0 | { |
186 | 0 | switch (st) { |
187 | 0 | case CERT_GOOD: |
188 | 0 | return 0; |
189 | 0 | case CERT_REVOKED: |
190 | 0 | return OCSP_CERT_REVOKED; |
191 | 0 | default: |
192 | 0 | return OCSP_CERT_UNKNOWN; |
193 | 0 | } |
194 | 0 | } |
195 | | |
196 | | int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, WOLFSSL* ssl) |
197 | 0 | { |
198 | 0 | int ret = WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL); |
199 | |
|
200 | 0 | WC_DECLARE_VAR(ocspRequest, OcspRequest, 1, 0); |
201 | |
|
202 | 0 | WOLFSSL_ENTER("CheckCertOCSP"); |
203 | | |
204 | |
|
205 | 0 | #ifdef WOLFSSL_SMALL_STACK |
206 | 0 | ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, |
207 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
208 | 0 | if (ocspRequest == NULL) { |
209 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
210 | 0 | return MEMORY_E; |
211 | 0 | } |
212 | 0 | #endif |
213 | | |
214 | 0 | if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, |
215 | 0 | ocsp->cm->heap) == 0) { |
216 | 0 | ocspRequest->ssl = ssl; |
217 | 0 | ret = CheckOcspRequest(ocsp, ocspRequest, NULL, NULL); |
218 | |
|
219 | 0 | FreeOcspRequest(ocspRequest); |
220 | 0 | } |
221 | |
|
222 | 0 | WC_FREE_VAR_EX(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
223 | |
|
224 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", ret); |
225 | 0 | return ret; |
226 | 0 | } |
227 | | int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) |
228 | 0 | { |
229 | 0 | return CheckCertOCSP_ex(ocsp, cert, NULL); |
230 | 0 | } |
231 | | |
232 | | static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, |
233 | | OcspEntry** entry) |
234 | 0 | { |
235 | 0 | WOLFSSL_ENTER("GetOcspEntry"); |
236 | |
|
237 | 0 | *entry = NULL; |
238 | |
|
239 | 0 | if (wc_LockMutex(&ocsp->ocspLock) != 0) { |
240 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); |
241 | 0 | return BAD_MUTEX_E; |
242 | 0 | } |
243 | | |
244 | 0 | for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next) |
245 | 0 | if (XMEMCMP((*entry)->issuerHash, request->issuerHash, |
246 | 0 | OCSP_DIGEST_SIZE) == 0 |
247 | 0 | && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash, |
248 | 0 | OCSP_DIGEST_SIZE) == 0) |
249 | 0 | break; |
250 | |
|
251 | 0 | if (*entry == NULL) { |
252 | 0 | *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), |
253 | 0 | ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); |
254 | 0 | if (*entry) { |
255 | 0 | InitOcspEntry(*entry, request); |
256 | 0 | (*entry)->next = ocsp->ocspList; |
257 | 0 | ocsp->ocspList = *entry; |
258 | 0 | } |
259 | 0 | } |
260 | |
|
261 | 0 | wc_UnLockMutex(&ocsp->ocspLock); |
262 | |
|
263 | 0 | return *entry ? 0 : MEMORY_ERROR; |
264 | 0 | } |
265 | | |
266 | | |
267 | | /* Mallocs responseBuffer->buffer and is up to caller to free on success |
268 | | * |
269 | | * Returns OCSP status |
270 | | */ |
271 | | static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, |
272 | | OcspEntry* entry, CertStatus** status, buffer* responseBuffer, |
273 | | void* heap) |
274 | 0 | { |
275 | 0 | int ret = WC_NO_ERR_TRACE(OCSP_INVALID_STATUS); |
276 | |
|
277 | 0 | WOLFSSL_ENTER("GetOcspStatus"); |
278 | |
|
279 | 0 | (void)heap; |
280 | 0 | *status = NULL; |
281 | |
|
282 | 0 | if (wc_LockMutex(&ocsp->ocspLock) != 0) { |
283 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); |
284 | 0 | return BAD_MUTEX_E; |
285 | 0 | } |
286 | | |
287 | 0 | for (*status = entry->status; *status; *status = (*status)->next) |
288 | 0 | if ((*status)->serialSz == request->serialSz |
289 | 0 | && !XMEMCMP((*status)->serial, request->serial, (size_t)(*status)->serialSz)) |
290 | 0 | break; |
291 | |
|
292 | 0 | if (responseBuffer && *status && !(*status)->rawOcspResponse) { |
293 | | /* force fetching again */ |
294 | 0 | ret = OCSP_INVALID_STATUS; |
295 | 0 | } |
296 | 0 | else if (*status) { |
297 | 0 | #ifndef NO_ASN_TIME |
298 | 0 | if (XVALIDATE_DATE((*status)->thisDate, |
299 | 0 | (*status)->thisDateFormat, ASN_BEFORE, MAX_DATE_SIZE) |
300 | 0 | && ((*status)->nextDate[0] != 0) |
301 | 0 | && XVALIDATE_DATE((*status)->nextDate, |
302 | 0 | (*status)->nextDateFormat, ASN_AFTER, MAX_DATE_SIZE)) |
303 | 0 | #endif |
304 | 0 | { |
305 | 0 | ret = xstat2err((*status)->status); |
306 | |
|
307 | 0 | if (responseBuffer) { |
308 | 0 | responseBuffer->buffer = (byte*)XMALLOC( |
309 | 0 | (*status)->rawOcspResponseSz, heap, |
310 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
311 | |
|
312 | 0 | if (responseBuffer->buffer) { |
313 | 0 | responseBuffer->length = (*status)->rawOcspResponseSz; |
314 | 0 | XMEMCPY(responseBuffer->buffer, |
315 | 0 | (*status)->rawOcspResponse, |
316 | 0 | (*status)->rawOcspResponseSz); |
317 | 0 | } |
318 | 0 | } |
319 | 0 | } |
320 | 0 | } |
321 | |
|
322 | 0 | wc_UnLockMutex(&ocsp->ocspLock); |
323 | |
|
324 | 0 | return ret; |
325 | 0 | } |
326 | | |
327 | | /* Check that the response for validity. Store result in status. |
328 | | * |
329 | | * ocsp Context object for OCSP status. |
330 | | * response OCSP response message data. |
331 | | * responseSz Length of OCSP response message data. |
332 | | * responseBuffer Buffer object to return the response with. |
333 | | * status The certificate status object. |
334 | | * entry The OCSP entry for this certificate. |
335 | | * ocspRequest Request corresponding to response. |
336 | | * heap Heap hint used for responseBuffer |
337 | | * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. |
338 | | */ |
339 | | int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, |
340 | | WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status, |
341 | | OcspEntry *entry, OcspRequest *ocspRequest, void* heap) |
342 | 0 | { |
343 | 0 | #ifdef WOLFSSL_SMALL_STACK |
344 | 0 | CertStatus* newStatus; |
345 | 0 | OcspEntry* newSingle; |
346 | 0 | OcspResponse* ocspResponse; |
347 | | #else |
348 | | CertStatus newStatus[1]; |
349 | | OcspEntry newSingle[1]; |
350 | | OcspResponse ocspResponse[1]; |
351 | | #endif |
352 | 0 | int ret; |
353 | 0 | int validated = 0; /* ocsp validation flag */ |
354 | |
|
355 | 0 | (void)heap; |
356 | |
|
357 | 0 | #ifdef WOLFSSL_SMALL_STACK |
358 | 0 | newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, |
359 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
360 | 0 | newSingle = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, |
361 | 0 | DYNAMIC_TYPE_OCSP_ENTRY); |
362 | 0 | ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, |
363 | 0 | DYNAMIC_TYPE_OCSP_REQUEST); |
364 | |
|
365 | 0 | if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) { |
366 | 0 | XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); |
367 | 0 | XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
368 | 0 | XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
369 | |
|
370 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
371 | 0 | return MEMORY_E; |
372 | 0 | } |
373 | 0 | #endif |
374 | 0 | InitOcspResponse(ocspResponse, newSingle, newStatus, response, |
375 | 0 | (word32)responseSz, ocsp->cm->heap); |
376 | | #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(NO_TLS) |
377 | | if (ocspRequest != NULL && ocspRequest->ssl != NULL && |
378 | | TLSX_CSR2_IsMulti(((WOLFSSL*)ocspRequest->ssl)->extensions)) { |
379 | | ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions); |
380 | | } |
381 | | #endif |
382 | 0 | ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0, 0); |
383 | 0 | if (ret != 0) { |
384 | 0 | ocsp->error = ret; |
385 | 0 | WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error); |
386 | 0 | goto end; |
387 | 0 | } |
388 | | |
389 | 0 | if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { |
390 | 0 | WOLFSSL_MSG("OcspResponse status bad"); |
391 | 0 | goto end; |
392 | 0 | } |
393 | 0 | if (ocspRequest != NULL) { |
394 | | /* Has the chance to bubble up response changing ocspResponse->single to |
395 | | no longer be pointing at newSingle */ |
396 | 0 | ret = CompareOcspReqResp(ocspRequest, ocspResponse); |
397 | 0 | if (ret != 0) { |
398 | 0 | goto end; |
399 | 0 | } |
400 | 0 | } |
401 | | |
402 | 0 | if (responseBuffer) { |
403 | 0 | responseBuffer->buffer = (byte*)XMALLOC((size_t)responseSz, heap, |
404 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
405 | |
|
406 | 0 | if (responseBuffer->buffer) { |
407 | 0 | responseBuffer->length = (unsigned int)responseSz; |
408 | 0 | XMEMCPY(responseBuffer->buffer, response, (size_t)responseSz); |
409 | 0 | } |
410 | 0 | } |
411 | |
|
412 | 0 | ret = xstat2err(ocspResponse->single->status->status); |
413 | 0 | if (ret == 0) { |
414 | 0 | validated = 1; |
415 | 0 | } |
416 | |
|
417 | 0 | if (wc_LockMutex(&ocsp->ocspLock) != 0) { |
418 | 0 | ret = BAD_MUTEX_E; |
419 | 0 | goto end; |
420 | 0 | } |
421 | | |
422 | 0 | if (status != NULL) { |
423 | 0 | XFREE(status->rawOcspResponse, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); |
424 | | |
425 | | /* Replace existing certificate entry with updated */ |
426 | 0 | ocspResponse->single->status->next = status->next; |
427 | 0 | XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus)); |
428 | 0 | } |
429 | 0 | else if (entry != NULL) { |
430 | | /* Save new certificate entry */ |
431 | 0 | status = (CertStatus*)XMALLOC(sizeof(CertStatus), |
432 | 0 | ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); |
433 | 0 | if (status != NULL) { |
434 | 0 | XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus)); |
435 | 0 | status->next = entry->status; |
436 | 0 | entry->status = status; |
437 | 0 | entry->ownStatus = 1; |
438 | 0 | entry->totalStatus++; |
439 | 0 | } |
440 | 0 | } |
441 | |
|
442 | 0 | if (status && responseBuffer && responseBuffer->buffer) { |
443 | 0 | status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, |
444 | 0 | ocsp->cm->heap, |
445 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
446 | |
|
447 | 0 | if (status->rawOcspResponse) { |
448 | 0 | status->rawOcspResponseSz = responseBuffer->length; |
449 | 0 | XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, |
450 | 0 | responseBuffer->length); |
451 | 0 | } |
452 | 0 | } |
453 | |
|
454 | 0 | wc_UnLockMutex(&ocsp->ocspLock); |
455 | |
|
456 | 0 | end: |
457 | 0 | if (ret == 0 && validated == 1) { |
458 | 0 | WOLFSSL_MSG("New OcspResponse validated"); |
459 | 0 | } |
460 | 0 | else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED)) { |
461 | 0 | WOLFSSL_MSG("OCSP revoked"); |
462 | 0 | } |
463 | 0 | else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN)) { |
464 | 0 | WOLFSSL_MSG("OCSP unknown"); |
465 | 0 | } |
466 | 0 | else { |
467 | 0 | WOLFSSL_MSG("OCSP lookup failure"); |
468 | 0 | ret = OCSP_LOOKUP_FAIL; |
469 | 0 | } |
470 | |
|
471 | 0 | FreeOcspResponse(ocspResponse); |
472 | 0 | WC_FREE_VAR_EX(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS); |
473 | 0 | WC_FREE_VAR_EX(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
474 | 0 | WC_FREE_VAR_EX(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
475 | 0 | return ret; |
476 | 0 | } |
477 | | |
478 | | /* 0 on success */ |
479 | | /* allow user to override the maximum request size at build-time */ |
480 | | #ifndef OCSP_MAX_REQUEST_SZ |
481 | 0 | #define OCSP_MAX_REQUEST_SZ 2048 |
482 | | #endif |
483 | | int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, |
484 | | buffer* responseBuffer, void* heap) |
485 | 0 | { |
486 | 0 | OcspEntry* entry = NULL; |
487 | 0 | CertStatus* status = NULL; |
488 | 0 | byte* request = NULL; |
489 | 0 | int requestSz = OCSP_MAX_REQUEST_SZ; |
490 | 0 | int responseSz = 0; |
491 | 0 | byte* response = NULL; |
492 | 0 | const char* url = NULL; |
493 | 0 | int urlSz = 0; |
494 | 0 | int ret = -1; |
495 | 0 | WOLFSSL* ssl; |
496 | 0 | void* ioCtx; |
497 | |
|
498 | 0 | WOLFSSL_ENTER("CheckOcspRequest"); |
499 | |
|
500 | 0 | if (ocsp == NULL || ocspRequest == NULL) |
501 | 0 | return BAD_FUNC_ARG; |
502 | | |
503 | 0 | if (responseBuffer) { |
504 | 0 | responseBuffer->buffer = NULL; |
505 | 0 | responseBuffer->length = 0; |
506 | 0 | } |
507 | |
|
508 | 0 | ret = GetOcspEntry(ocsp, ocspRequest, &entry); |
509 | 0 | if (ret != 0) |
510 | 0 | return ret; |
511 | | |
512 | 0 | ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer, |
513 | 0 | heap); |
514 | 0 | if (ret != WC_NO_ERR_TRACE(OCSP_INVALID_STATUS)) |
515 | 0 | return ret; |
516 | | |
517 | 0 | if (responseBuffer) { |
518 | 0 | XFREE(responseBuffer->buffer, heap, DYNAMIC_TYPE_TMP_BUFFER); |
519 | 0 | responseBuffer->buffer = NULL; |
520 | 0 | } |
521 | | |
522 | | /* get SSL and IOCtx */ |
523 | 0 | ssl = (WOLFSSL*)ocspRequest->ssl; |
524 | 0 | ioCtx = (ssl && ssl->ocspIOCtx != NULL) ? |
525 | 0 | ssl->ocspIOCtx : ocsp->cm->ocspIOCtx; |
526 | |
|
527 | 0 | if (ocsp->cm->ocspUseOverrideURL) { |
528 | 0 | url = ocsp->cm->ocspOverrideURL; |
529 | 0 | if (url != NULL && url[0] != '\0') |
530 | 0 | urlSz = (int)XSTRLEN(url); |
531 | 0 | else |
532 | 0 | return OCSP_NEED_URL; |
533 | 0 | } |
534 | 0 | else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { |
535 | 0 | url = (const char *)ocspRequest->url; |
536 | 0 | urlSz = ocspRequest->urlSz; |
537 | 0 | } |
538 | 0 | else { |
539 | | /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ |
540 | 0 | WOLFSSL_MSG("Cert has no OCSP URL, assuming CERT_GOOD"); |
541 | 0 | return 0; |
542 | 0 | } |
543 | | |
544 | 0 | request = (byte*)XMALLOC((size_t)requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); |
545 | 0 | if (request == NULL) { |
546 | 0 | WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); |
547 | 0 | return MEMORY_ERROR; |
548 | 0 | } |
549 | | |
550 | 0 | requestSz = EncodeOcspRequest(ocspRequest, request, (word32)requestSz); |
551 | 0 | if (requestSz > 0 && ocsp->cm->ocspIOCb) { |
552 | 0 | responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz, |
553 | 0 | request, requestSz, &response); |
554 | 0 | } |
555 | 0 | if (responseSz == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) { |
556 | 0 | ret = OCSP_WANT_READ; |
557 | 0 | } |
558 | 0 | else if (responseSz == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_TIMEOUT)){ |
559 | 0 | ret = HTTP_TIMEOUT; |
560 | 0 | } |
561 | |
|
562 | 0 | XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); |
563 | |
|
564 | 0 | if (responseSz >= 0 && response) { |
565 | 0 | ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status, |
566 | 0 | entry, ocspRequest, heap); |
567 | 0 | } |
568 | |
|
569 | 0 | if (response != NULL && ocsp->cm->ocspRespFreeCb) |
570 | 0 | ocsp->cm->ocspRespFreeCb(ioCtx, response); |
571 | | |
572 | | /* Keep responseBuffer in the case of getting to response check. Caller |
573 | | * should free responseBuffer after checking OCSP return value in "ret" */ |
574 | 0 | WOLFSSL_LEAVE("CheckOcspRequest", ret); |
575 | 0 | return ret; |
576 | 0 | } |
577 | | |
578 | | #ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK |
579 | | static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, |
580 | 0 | void* vp, Signer* pendingCAs) { |
581 | | /* Attempt to build a chain up to cert's issuer */ |
582 | 0 | WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; |
583 | 0 | Signer* ca = NULL; |
584 | 0 | Signer* prev = NULL; |
585 | 0 | int passed = 0; |
586 | | |
587 | | /* |
588 | | * Relation between certs: |
589 | | * CA |
590 | | * / \ |
591 | | * intermediate(s) cert in OCSP response |
592 | | * | with OCSP key usage ext |
593 | | * issuer of cert |
594 | | * in OCSP request |
595 | | */ |
596 | | |
597 | | /* End loop if no more issuers found or if we have found a self |
598 | | * signed cert (ca == prev) */ |
599 | 0 | ca = GetCAByName(cm, single->issuerHash); |
600 | | #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) |
601 | | if (ca == NULL && pendingCAs != NULL) { |
602 | | ca = findSignerByName(pendingCAs, single->issuerHash); |
603 | | } |
604 | | #else |
605 | 0 | (void)pendingCAs; |
606 | 0 | #endif |
607 | 0 | for (; ca != NULL && ca != prev; |
608 | 0 | prev = ca) { |
609 | 0 | if (XMEMCMP(cert->issuerHash, ca->issuerNameHash, |
610 | 0 | OCSP_DIGEST_SIZE) == 0) { |
611 | 0 | WOLFSSL_MSG("\tOCSP Response signed by authorized " |
612 | 0 | "responder delegated by issuer " |
613 | 0 | "(found in chain)"); |
614 | 0 | passed = 1; |
615 | 0 | break; |
616 | 0 | } |
617 | 0 | ca = GetCAByName(cm, ca->issuerNameHash); |
618 | | #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) |
619 | | if (ca == NULL && pendingCAs != NULL) { |
620 | | ca = findSignerByName(pendingCAs, single->issuerHash); |
621 | | } |
622 | | #endif |
623 | 0 | } |
624 | 0 | return passed; |
625 | 0 | } |
626 | | #endif |
627 | | |
628 | | /** |
629 | | * Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2 |
630 | | * @param bs The basic response to verify |
631 | | * @param cert The decoded bs->cert |
632 | | * @return |
633 | | */ |
634 | | int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp) |
635 | 0 | { |
636 | 0 | int ret = 0; |
637 | 0 | OcspEntry* single; |
638 | | |
639 | | /* Both evaluate to enum values so can't use a pre-processor check */ |
640 | 0 | WOLFSSL_ASSERT_EQ(OCSP_DIGEST_SIZE, SIGNER_DIGEST_SIZE); |
641 | |
|
642 | 0 | (void)vp; |
643 | |
|
644 | 0 | WOLFSSL_ENTER("CheckOcspResponder"); |
645 | | |
646 | | /* In the future if this API is used more then it could be beneficial to |
647 | | * implement calling InitDecodedCert and ParseCertRelative here |
648 | | * automatically when cert == NULL. */ |
649 | 0 | if (bs == NULL || cert == NULL) |
650 | 0 | return BAD_FUNC_ARG; |
651 | | |
652 | | /* Traverse the list and check that the cert has the authority to provide |
653 | | * an OCSP response for each entry. */ |
654 | 0 | for (single = bs->single; single != NULL; single = single->next) { |
655 | 0 | int passed = 0; |
656 | |
|
657 | 0 | if (XMEMCMP(cert->subjectHash, single->issuerHash, OCSP_DIGEST_SIZE) |
658 | 0 | == 0) { |
659 | 0 | WOLFSSL_MSG("\tOCSP Response signed by issuer"); |
660 | 0 | passed = 1; |
661 | 0 | } |
662 | 0 | else if ((cert->extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) != 0) { |
663 | 0 | if (XMEMCMP(cert->issuerHash, single->issuerHash, |
664 | 0 | OCSP_DIGEST_SIZE) == 0) { |
665 | 0 | WOLFSSL_MSG("\tOCSP Response signed by authorized responder " |
666 | 0 | "delegated by issuer"); |
667 | 0 | passed = 1; |
668 | 0 | } |
669 | 0 | #ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK |
670 | 0 | else if (vp != NULL) { |
671 | 0 | passed = CheckOcspResponderChain(single, cert, vp, bs->pendingCAs); |
672 | 0 | } |
673 | 0 | #endif |
674 | 0 | } |
675 | |
|
676 | 0 | if (!passed) { |
677 | 0 | WOLFSSL_MSG("\tOCSP Responder not authorized"); |
678 | 0 | ret = BAD_OCSP_RESPONDER; |
679 | 0 | break; |
680 | 0 | } |
681 | 0 | } |
682 | 0 | return ret; |
683 | 0 | } |
684 | | |
685 | | |
686 | | /* compatibility layer OCSP functions */ |
687 | | #ifdef OPENSSL_EXTRA |
688 | | int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, |
689 | | WOLFSSL_OCSP_CERTID* id, int* status, int* reason, |
690 | | WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, |
691 | | WOLFSSL_ASN1_TIME** nextupd) |
692 | 0 | { |
693 | 0 | WOLFSSL_OCSP_SINGLERESP* single; |
694 | |
|
695 | 0 | if (bs == NULL || id == NULL) |
696 | 0 | return WOLFSSL_FAILURE; |
697 | | |
698 | 0 | single = bs->single; |
699 | 0 | while (single != NULL) { |
700 | 0 | if ((XMEMCMP(single->status->serial, id->status->serial, (size_t)single->status->serialSz) == 0) |
701 | 0 | && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0) |
702 | 0 | && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) { |
703 | 0 | break; |
704 | 0 | } |
705 | 0 | single = single->next; |
706 | 0 | } |
707 | |
|
708 | 0 | if (single == NULL) |
709 | 0 | return WOLFSSL_FAILURE; |
710 | | |
711 | 0 | if (status != NULL) |
712 | 0 | *status = single->status->status; |
713 | 0 | #ifdef WOLFSSL_OCSP_PARSE_STATUS |
714 | 0 | if (thisupd != NULL) |
715 | 0 | *thisupd = &single->status->thisDateParsed; |
716 | 0 | if (nextupd != NULL) |
717 | 0 | *nextupd = &single->status->nextDateParsed; |
718 | | #else |
719 | | if (thisupd != NULL) |
720 | | *thisupd = NULL; |
721 | | if (nextupd != NULL) |
722 | | *nextupd = NULL; |
723 | | #endif |
724 | | |
725 | | /* TODO: Not needed for Nginx or httpd */ |
726 | 0 | if (reason != NULL) |
727 | 0 | *reason = 0; |
728 | 0 | if (revtime != NULL) |
729 | 0 | *revtime = NULL; |
730 | |
|
731 | 0 | return WOLFSSL_SUCCESS; |
732 | 0 | } |
733 | | |
734 | | const char *wolfSSL_OCSP_cert_status_str(long s) |
735 | 0 | { |
736 | 0 | switch (s) { |
737 | 0 | case CERT_GOOD: |
738 | 0 | return "good"; |
739 | 0 | case CERT_REVOKED: |
740 | 0 | return "revoked"; |
741 | 0 | case CERT_UNKNOWN: |
742 | 0 | return "unknown"; |
743 | 0 | default: |
744 | 0 | return "(UNKNOWN)"; |
745 | 0 | } |
746 | 0 | } |
747 | | |
748 | | int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, |
749 | | WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) |
750 | 0 | { |
751 | 0 | (void)thisupd; |
752 | 0 | (void)nextupd; |
753 | 0 | (void)sec; |
754 | 0 | (void)maxsec; |
755 | | /* Dates validated in DecodeSingleResponse. */ |
756 | 0 | return WOLFSSL_SUCCESS; |
757 | 0 | } |
758 | | |
759 | | void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) |
760 | 0 | { |
761 | 0 | FreeOcspEntry(certId, NULL); |
762 | 0 | XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); |
763 | 0 | } |
764 | | |
765 | | WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( |
766 | | const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, |
767 | | const WOLFSSL_X509 *issuer) |
768 | 0 | { |
769 | 0 | WOLFSSL_OCSP_CERTID* certId = NULL; |
770 | 0 | CertStatus* certStatus = NULL; |
771 | 0 | WOLFSSL_CERT_MANAGER* cm = NULL; |
772 | 0 | int ret = -1; |
773 | 0 | DerBuffer* derCert = NULL; |
774 | 0 | int dgstType; |
775 | 0 | WC_DECLARE_VAR(cert, DecodedCert, 1, 0); |
776 | |
|
777 | 0 | if (dgst == NULL) { |
778 | 0 | dgstType = WC_HASH_TYPE_SHA; |
779 | 0 | } |
780 | 0 | else if (wolfSSL_EVP_get_hashinfo(dgst, &dgstType, NULL) != |
781 | 0 | WOLFSSL_SUCCESS) { |
782 | 0 | return NULL; |
783 | 0 | } |
784 | | |
785 | 0 | if (dgstType != OCSP_DIGEST) |
786 | 0 | return NULL; |
787 | | |
788 | 0 | cm = wolfSSL_CertManagerNew(); |
789 | 0 | if (cm == NULL |
790 | 0 | || subject == NULL || subject->derCert == NULL |
791 | 0 | || issuer == NULL || issuer->derCert == NULL) |
792 | 0 | goto out; |
793 | | |
794 | 0 | WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT, |
795 | 0 | goto out); |
796 | | |
797 | 0 | ret = AllocDer(&derCert, issuer->derCert->length, |
798 | 0 | issuer->derCert->type, NULL); |
799 | 0 | if (ret == 0) { |
800 | | /* AddCA() frees the buffer. */ |
801 | 0 | XMEMCPY(derCert->buffer, issuer->derCert->buffer, |
802 | 0 | issuer->derCert->length); |
803 | 0 | ret = AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); |
804 | 0 | if (ret != WOLFSSL_SUCCESS) { |
805 | 0 | goto out; |
806 | 0 | } |
807 | 0 | derCert = NULL; |
808 | 0 | } |
809 | | |
810 | 0 | ret = -1; |
811 | |
|
812 | 0 | certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), |
813 | 0 | cm->heap, DYNAMIC_TYPE_OPENSSL); |
814 | 0 | if (certId == NULL) |
815 | 0 | goto out; |
816 | | |
817 | 0 | certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), cm->heap, |
818 | 0 | DYNAMIC_TYPE_OPENSSL); |
819 | 0 | if (certStatus == NULL) |
820 | 0 | goto out; |
821 | | |
822 | 0 | XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); |
823 | 0 | XMEMSET(certStatus, 0, sizeof(CertStatus)); |
824 | |
|
825 | 0 | certId->status = certStatus; |
826 | 0 | certId->ownStatus = 1; |
827 | |
|
828 | 0 | InitDecodedCert(cert, subject->derCert->buffer, |
829 | 0 | subject->derCert->length, NULL); |
830 | 0 | if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL) != 0) { |
831 | 0 | FreeDecodedCert(cert); |
832 | 0 | goto out; |
833 | 0 | } |
834 | 0 | else { |
835 | 0 | certId->hashAlgoOID = wc_HashGetOID(OCSP_DIGEST); |
836 | 0 | XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE); |
837 | 0 | XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE); |
838 | 0 | XMEMCPY(certId->status->serial, cert->serial, (size_t)cert->serialSz); |
839 | 0 | certId->status->serialSz = cert->serialSz; |
840 | 0 | FreeDecodedCert(cert); |
841 | 0 | } |
842 | | |
843 | 0 | ret = 0; |
844 | |
|
845 | 0 | out: |
846 | |
|
847 | 0 | if (ret != 0) { |
848 | 0 | if (derCert != NULL) |
849 | 0 | FreeDer(&derCert); |
850 | 0 | if (cm != NULL) { |
851 | 0 | XFREE(certId, cm->heap, DYNAMIC_TYPE_OPENSSL); |
852 | 0 | certId = NULL; |
853 | 0 | XFREE(certStatus, cm->heap, DYNAMIC_TYPE_OPENSSL); |
854 | 0 | } |
855 | 0 | } |
856 | |
|
857 | 0 | #ifdef WOLFSSL_SMALL_STACK |
858 | 0 | if (cm != NULL) |
859 | 0 | XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); |
860 | 0 | #endif |
861 | |
|
862 | 0 | if (cm != NULL) |
863 | 0 | wolfSSL_CertManagerFree(cm); |
864 | |
|
865 | 0 | return certId; |
866 | 0 | } |
867 | | |
868 | | void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) |
869 | 0 | { |
870 | 0 | wolfSSL_OCSP_RESPONSE_free(basicResponse); |
871 | 0 | } |
872 | | |
873 | | /* Calculate ancode CertID DER encoding following RFC 6960: |
874 | | CertID ::= SEQUENCE { |
875 | | hashAlgorithm AlgorithmIdentifier, |
876 | | issuerNameHash OCTET STRING, |
877 | | issuerKeyHash OCTET STRING, |
878 | | serialNumber CertificateSerialNumber } |
879 | | */ |
880 | | static int OcspEncodeCertID(WOLFSSL_OCSP_CERTID* id, byte* output, |
881 | | word32* totalSz, word32* intSize) |
882 | 0 | { |
883 | 0 | word32 idx = 0; |
884 | 0 | int ret; |
885 | |
|
886 | 0 | if (id == NULL || totalSz == NULL || intSize == NULL || |
887 | 0 | (output != NULL && (*totalSz == 0 || *totalSz <= *intSize))) |
888 | 0 | return BAD_FUNC_ARG; |
889 | | |
890 | 0 | if (output != NULL) { |
891 | 0 | ret = SetSequence(*intSize, output); |
892 | 0 | if (ret < 0) |
893 | 0 | return ret; |
894 | 0 | idx += ret; |
895 | 0 | } |
896 | | |
897 | 0 | ret = SetAlgoID(id->hashAlgoOID, ((output != NULL) ? output + idx : output), |
898 | 0 | oidHashType, 0); |
899 | 0 | if (ret <= 0) |
900 | 0 | return -1; |
901 | 0 | idx += ret; |
902 | | |
903 | | /* issuerNameHash */ |
904 | 0 | ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output)); |
905 | 0 | if (ret < 0) |
906 | 0 | return ret; |
907 | 0 | idx += ret; |
908 | 0 | if (output != NULL) |
909 | 0 | XMEMCPY(output + idx, id->issuerHash, OCSP_DIGEST_SIZE); |
910 | 0 | idx += OCSP_DIGEST_SIZE; |
911 | | |
912 | | /* issuerKeyHash */ |
913 | 0 | ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output)); |
914 | 0 | if (ret < 0) |
915 | 0 | return ret; |
916 | 0 | idx += ret; |
917 | 0 | if (output != NULL) |
918 | 0 | XMEMCPY(output + idx, id->issuerKeyHash, OCSP_DIGEST_SIZE); |
919 | 0 | idx += OCSP_DIGEST_SIZE; |
920 | | |
921 | | /* serialNumber */ |
922 | 0 | ret = SetASNInt(id->status->serialSz, id->status->serial[0], ((output != NULL) ? output + idx : output)); |
923 | 0 | if (ret < 0) |
924 | 0 | return ret; |
925 | 0 | idx += ret; |
926 | 0 | if (output != NULL) |
927 | 0 | XMEMCPY(output + idx, id->status->serial, id->status->serialSz); |
928 | 0 | idx += id->status->serialSz; |
929 | |
|
930 | 0 | if (output == NULL) { |
931 | 0 | *intSize = idx; |
932 | 0 | ret = SetSequence(idx, NULL); |
933 | 0 | if (ret < 0) |
934 | 0 | return ret; |
935 | 0 | idx += ret; |
936 | 0 | *totalSz = idx; |
937 | 0 | } |
938 | 0 | else if (idx != *totalSz) { |
939 | 0 | return BUFFER_E; |
940 | 0 | } |
941 | | |
942 | 0 | return 0; |
943 | 0 | } |
944 | | |
945 | | static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash, |
946 | | const byte* keyHash) |
947 | 0 | { |
948 | 0 | if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) { |
949 | 0 | return XMEMCMP(NameHash, resp->responderId.nameHash, |
950 | 0 | SIGNER_DIGEST_SIZE) == 0; |
951 | 0 | } |
952 | 0 | else if (resp->responderIdType == OCSP_RESPONDER_ID_KEY) { |
953 | 0 | return XMEMCMP(keyHash, resp->responderId.keyHash, KEYID_SIZE) == 0; |
954 | 0 | } |
955 | | |
956 | 0 | return 0; |
957 | 0 | } |
958 | | |
959 | | static int OcspFindSigner(WOLFSSL_OCSP_BASICRESP *resp, |
960 | | WOLF_STACK_OF(WOLFSSL_X509) *certs, DecodedCert **signer, int *embedded, |
961 | | unsigned long flags) |
962 | 0 | { |
963 | 0 | WOLFSSL_X509 *signer_x509 = NULL; |
964 | 0 | DecodedCert *certDecoded; |
965 | 0 | int i; |
966 | |
|
967 | 0 | certDecoded = (DecodedCert *)XMALLOC(sizeof(*certDecoded), resp->heap, |
968 | 0 | DYNAMIC_TYPE_DCERT); |
969 | 0 | if (certDecoded == NULL) |
970 | 0 | return MEMORY_E; |
971 | | |
972 | 0 | for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) { |
973 | 0 | signer_x509 = wolfSSL_sk_X509_value(certs, i); |
974 | 0 | if (signer_x509 == NULL) |
975 | 0 | continue; |
976 | | |
977 | 0 | InitDecodedCert(certDecoded, signer_x509->derCert->buffer, |
978 | 0 | signer_x509->derCert->length, resp->heap); |
979 | 0 | if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY, |
980 | 0 | NULL, NULL) == 0) { |
981 | 0 | if (OcspRespIdMatches(resp, certDecoded->subjectHash, |
982 | 0 | certDecoded->subjectKeyHash)) { |
983 | 0 | *signer = certDecoded; |
984 | 0 | *embedded = 0; |
985 | 0 | return 0; |
986 | 0 | } |
987 | 0 | } |
988 | 0 | FreeDecodedCert(certDecoded); |
989 | 0 | } |
990 | | |
991 | 0 | if (flags & WOLFSSL_OCSP_NOINTERN) { |
992 | 0 | XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT); |
993 | 0 | return ASN_NO_SIGNER_E; |
994 | 0 | } |
995 | | |
996 | | /* not found in certs, search the cert embedded in the response */ |
997 | 0 | InitDecodedCert(certDecoded, resp->cert, resp->certSz, resp->heap); |
998 | 0 | if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0) { |
999 | 0 | if (OcspRespIdMatches(resp, certDecoded->subjectHash, |
1000 | 0 | certDecoded->subjectKeyHash)) { |
1001 | 0 | *signer = certDecoded; |
1002 | 0 | *embedded = 1; |
1003 | 0 | return 0; |
1004 | 0 | } |
1005 | 0 | } |
1006 | 0 | FreeDecodedCert(certDecoded); |
1007 | |
|
1008 | 0 | XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT); |
1009 | 0 | return ASN_NO_SIGNER_E; |
1010 | 0 | } |
1011 | | |
1012 | | static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert, |
1013 | | WOLFSSL_X509_STORE *st, unsigned long flags) |
1014 | 0 | { |
1015 | 0 | WC_DECLARE_VAR(c, DecodedCert, 1, 0); |
1016 | |
|
1017 | 0 | int ret = -1; |
1018 | 0 | if (st == NULL) |
1019 | 0 | return ASN_OCSP_CONFIRM_E; |
1020 | | |
1021 | 0 | WC_ALLOC_VAR_EX(c, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT, |
1022 | 0 | return MEMORY_E); |
1023 | | |
1024 | 0 | InitDecodedCert(c, cert->source, cert->maxIdx, NULL); |
1025 | 0 | if (ParseCertRelative(c, CERT_TYPE, VERIFY, st->cm, NULL) != 0) { |
1026 | 0 | ret = ASN_OCSP_CONFIRM_E; |
1027 | 0 | goto err; |
1028 | 0 | } |
1029 | 0 | #ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK |
1030 | 0 | if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) { |
1031 | 0 | ret = CheckOcspResponder(resp, c, st->cm); |
1032 | 0 | } |
1033 | 0 | else { |
1034 | 0 | ret = 0; |
1035 | 0 | } |
1036 | | #else |
1037 | | (void)resp; |
1038 | | (void)flags; |
1039 | | ret = 0; |
1040 | | #endif |
1041 | |
|
1042 | 0 | err: |
1043 | 0 | FreeDecodedCert(c); |
1044 | 0 | WC_FREE_VAR_EX(c, NULL, DYNAMIC_TYPE_DCERT); |
1045 | 0 | return ret; |
1046 | 0 | } |
1047 | | /* Signature verified in DecodeBasicOcspResponse. |
1048 | | * But no store available to verify certificate. */ |
1049 | | int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP* bs, |
1050 | | WOLF_STACK_OF(WOLFSSL_X509) * certs, WOLFSSL_X509_STORE* st, |
1051 | | unsigned long flags) |
1052 | 0 | { |
1053 | 0 | int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); |
1054 | 0 | int embedded; |
1055 | 0 | DecodedCert *cert = NULL; |
1056 | |
|
1057 | 0 | ret = OcspFindSigner(bs, certs, &cert, &embedded, flags); |
1058 | 0 | if (ret != 0) { |
1059 | 0 | WOLFSSL_MSG("OCSP no signer found"); |
1060 | 0 | return WOLFSSL_FAILURE; |
1061 | 0 | } |
1062 | | |
1063 | | /* skip certificate verification if cert in certs and TRUST_OTHER is true */ |
1064 | 0 | if (!embedded && (flags & WOLFSSL_OCSP_TRUSTOTHER) != 0) |
1065 | 0 | flags |= WOLFSSL_OCSP_NOVERIFY; |
1066 | | |
1067 | | /* verify response signature */ |
1068 | 0 | ret = ConfirmSignature( |
1069 | 0 | &cert->sigCtx, |
1070 | 0 | bs->response, bs->responseSz, |
1071 | 0 | cert->publicKey, cert->pubKeySize, cert->keyOID, |
1072 | 0 | bs->sig, bs->sigSz, bs->sigOID, bs->sigParams, bs->sigParamsSz, |
1073 | 0 | NULL); |
1074 | |
|
1075 | 0 | if (ret != 0) { |
1076 | 0 | WOLFSSL_MSG("OCSP signature verification failed"); |
1077 | 0 | ret = -1; |
1078 | 0 | goto err; |
1079 | 0 | } |
1080 | | |
1081 | 0 | if ((flags & WOLFSSL_OCSP_NOVERIFY) == 0) { |
1082 | 0 | ret = OcspVerifySigner(bs, cert, st, flags); |
1083 | 0 | } |
1084 | |
|
1085 | 0 | err: |
1086 | 0 | FreeDecodedCert(cert); |
1087 | 0 | XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); |
1088 | 0 | return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; |
1089 | 0 | } |
1090 | | |
1091 | | void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) |
1092 | 0 | { |
1093 | 0 | OcspEntry *s, *sNext; |
1094 | 0 | if (response == NULL) |
1095 | 0 | return; |
1096 | | |
1097 | | |
1098 | 0 | s = response->single; |
1099 | 0 | while (s != NULL) { |
1100 | 0 | sNext = s->next; |
1101 | 0 | FreeOcspEntry(s, NULL); |
1102 | 0 | XFREE(s, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
1103 | 0 | s = sNext; |
1104 | 0 | } |
1105 | |
|
1106 | 0 | XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
1107 | |
|
1108 | 0 | XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
1109 | 0 | } |
1110 | | |
1111 | | #ifndef NO_BIO |
1112 | | OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, |
1113 | | OcspResponse** response) |
1114 | 0 | { |
1115 | 0 | byte* data; |
1116 | 0 | byte* p; |
1117 | 0 | int len; |
1118 | 0 | int dataAlloced = 0; |
1119 | 0 | OcspResponse* ret = NULL; |
1120 | |
|
1121 | 0 | if (bio == NULL) |
1122 | 0 | return NULL; |
1123 | | |
1124 | 0 | if (bio->type == WOLFSSL_BIO_MEMORY) { |
1125 | 0 | len = wolfSSL_BIO_get_mem_data(bio, &data); |
1126 | 0 | if (len <= 0 || data == NULL) { |
1127 | 0 | return NULL; |
1128 | 0 | } |
1129 | 0 | } |
1130 | 0 | #ifndef NO_FILESYSTEM |
1131 | 0 | else if (bio->type == WOLFSSL_BIO_FILE) { |
1132 | 0 | long fcur; |
1133 | 0 | long flen; |
1134 | |
|
1135 | 0 | if (bio->ptr.fh == NULL) |
1136 | 0 | return NULL; |
1137 | | |
1138 | 0 | fcur = XFTELL(bio->ptr.fh); |
1139 | 0 | if (fcur < 0) |
1140 | 0 | return NULL; |
1141 | 0 | if(XFSEEK(bio->ptr.fh, 0, SEEK_END) != 0) |
1142 | 0 | return NULL; |
1143 | 0 | flen = XFTELL(bio->ptr.fh); |
1144 | 0 | if (flen < 0) |
1145 | 0 | return NULL; |
1146 | 0 | if (XFSEEK(bio->ptr.fh, fcur, SEEK_SET) != 0) |
1147 | 0 | return NULL; |
1148 | | |
1149 | | /* check calculated length */ |
1150 | 0 | fcur = flen - fcur; |
1151 | 0 | if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0) |
1152 | 0 | return NULL; |
1153 | | |
1154 | 0 | data = (byte*)XMALLOC((size_t)fcur, 0, DYNAMIC_TYPE_TMP_BUFFER); |
1155 | 0 | if (data == NULL) |
1156 | 0 | return NULL; |
1157 | 0 | dataAlloced = 1; |
1158 | |
|
1159 | 0 | len = wolfSSL_BIO_read(bio, (char *)data, (int)flen); |
1160 | 0 | } |
1161 | 0 | #endif |
1162 | 0 | else |
1163 | 0 | return NULL; |
1164 | | |
1165 | 0 | if (len > 0) { |
1166 | 0 | p = data; |
1167 | 0 | ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, |
1168 | 0 | len); |
1169 | 0 | } |
1170 | |
|
1171 | 0 | if (dataAlloced) |
1172 | 0 | XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); |
1173 | |
|
1174 | 0 | return ret; |
1175 | 0 | } |
1176 | | #endif /* !NO_BIO */ |
1177 | | |
1178 | | OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, |
1179 | | const unsigned char** data, int len) |
1180 | 0 | { |
1181 | 0 | OcspResponse *resp = NULL; |
1182 | 0 | word32 idx = 0; |
1183 | 0 | int length = 0; |
1184 | 0 | int ret; |
1185 | |
|
1186 | 0 | if (data == NULL) |
1187 | 0 | return NULL; |
1188 | | |
1189 | 0 | if (response != NULL) |
1190 | 0 | resp = *response; |
1191 | 0 | if (resp == NULL) { |
1192 | 0 | resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, |
1193 | 0 | DYNAMIC_TYPE_OCSP_REQUEST); |
1194 | 0 | if (resp == NULL) |
1195 | 0 | return NULL; |
1196 | 0 | XMEMSET(resp, 0, sizeof(OcspResponse)); |
1197 | 0 | } |
1198 | | |
1199 | 0 | resp->source = (byte*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
1200 | 0 | if (resp->source == NULL) { |
1201 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
1202 | 0 | return NULL; |
1203 | 0 | } |
1204 | 0 | resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, |
1205 | 0 | DYNAMIC_TYPE_OCSP_ENTRY); |
1206 | 0 | if (resp->single == NULL) { |
1207 | 0 | XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
1208 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
1209 | 0 | return NULL; |
1210 | 0 | } |
1211 | 0 | XMEMSET(resp->single, 0, sizeof(OcspEntry)); |
1212 | 0 | resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, |
1213 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
1214 | 0 | resp->single->ownStatus = 1; |
1215 | 0 | if (resp->single->status == NULL) { |
1216 | 0 | XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
1217 | 0 | XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY); |
1218 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); |
1219 | 0 | return NULL; |
1220 | 0 | } |
1221 | 0 | XMEMSET(resp->single->status, 0, sizeof(CertStatus)); |
1222 | |
|
1223 | 0 | XMEMCPY(resp->source, *data, (size_t)len); |
1224 | 0 | resp->maxIdx = (word32)len; |
1225 | |
|
1226 | 0 | ret = OcspResponseDecode(resp, NULL, NULL, 1, 1); |
1227 | 0 | if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) { |
1228 | | /* for just converting from a DER to an internal structure the CA may |
1229 | | * not yet be known to this function for signature verification */ |
1230 | 0 | wolfSSL_OCSP_RESPONSE_free(resp); |
1231 | 0 | return NULL; |
1232 | 0 | } |
1233 | | |
1234 | 0 | if (GetSequence(*data, &idx, &length, (word32)len) >= 0) |
1235 | 0 | (*data) += (unsigned char) ((int)idx + length); |
1236 | |
|
1237 | 0 | if (response != NULL && *response == NULL) |
1238 | 0 | *response = resp; |
1239 | |
|
1240 | 0 | return resp; |
1241 | 0 | } |
1242 | | |
1243 | | int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, |
1244 | | unsigned char** data) |
1245 | 0 | { |
1246 | 0 | if (data == NULL) |
1247 | 0 | return (int)response->maxIdx; |
1248 | | |
1249 | 0 | XMEMCPY(*data, response->source, response->maxIdx); |
1250 | 0 | return (int)response->maxIdx; |
1251 | 0 | } |
1252 | | |
1253 | | int wolfSSL_OCSP_response_status(OcspResponse *response) |
1254 | 0 | { |
1255 | 0 | return response->responseStatus; |
1256 | 0 | } |
1257 | | |
1258 | | const char *wolfSSL_OCSP_response_status_str(long s) |
1259 | 0 | { |
1260 | 0 | switch (s) { |
1261 | 0 | case OCSP_SUCCESSFUL: |
1262 | 0 | return "successful"; |
1263 | 0 | case OCSP_MALFORMED_REQUEST: |
1264 | 0 | return "malformedrequest"; |
1265 | 0 | case OCSP_INTERNAL_ERROR: |
1266 | 0 | return "internalerror"; |
1267 | 0 | case OCSP_TRY_LATER: |
1268 | 0 | return "trylater"; |
1269 | 0 | case OCSP_SIG_REQUIRED: |
1270 | 0 | return "sigrequired"; |
1271 | 0 | case OCSP_UNAUTHORIZED: |
1272 | 0 | return "unauthorized"; |
1273 | 0 | default: |
1274 | 0 | return "(UNKNOWN)"; |
1275 | 0 | } |
1276 | 0 | } |
1277 | | |
1278 | | WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) |
1279 | 0 | { |
1280 | 0 | WOLFSSL_OCSP_BASICRESP* bs; |
1281 | 0 | const unsigned char *ptr = response->source; |
1282 | |
|
1283 | 0 | bs = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, response->maxIdx); |
1284 | 0 | return bs; |
1285 | 0 | } |
1286 | | |
1287 | | OcspRequest* wolfSSL_OCSP_REQUEST_new(void) |
1288 | 0 | { |
1289 | 0 | OcspRequest* request; |
1290 | |
|
1291 | 0 | request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, |
1292 | 0 | DYNAMIC_TYPE_OPENSSL); |
1293 | 0 | if (request != NULL) |
1294 | 0 | XMEMSET(request, 0, sizeof(OcspRequest)); |
1295 | |
|
1296 | 0 | return request; |
1297 | 0 | } |
1298 | | |
1299 | | void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) |
1300 | 0 | { |
1301 | 0 | FreeOcspRequest(request); |
1302 | 0 | XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL); |
1303 | 0 | } |
1304 | | |
1305 | | int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) |
1306 | 0 | { |
1307 | 0 | int size; |
1308 | |
|
1309 | 0 | if (request == NULL) |
1310 | 0 | return BAD_FUNC_ARG; |
1311 | | |
1312 | 0 | size = EncodeOcspRequest(request, NULL, 0); |
1313 | 0 | if (size <= 0 || data == NULL) |
1314 | 0 | return size; |
1315 | | |
1316 | 0 | return EncodeOcspRequest(request, *data, (word32) size); |
1317 | 0 | } |
1318 | | |
1319 | | WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, |
1320 | | WOLFSSL_OCSP_CERTID *cid) |
1321 | 0 | { |
1322 | 0 | if (req == NULL || cid == NULL || cid->status == NULL) |
1323 | 0 | return NULL; |
1324 | | |
1325 | 0 | if (req->cid != NULL) |
1326 | 0 | wolfSSL_OCSP_CERTID_free((WOLFSSL_OCSP_CERTID*)req->cid); |
1327 | | /* Keep to free */ |
1328 | 0 | req->cid = (void*)cid; |
1329 | |
|
1330 | 0 | XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE); |
1331 | 0 | XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE); |
1332 | 0 | if (cid->status->serialSz > req->serialSz) { |
1333 | 0 | XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); |
1334 | 0 | req->serial = (byte*)XMALLOC((size_t)cid->status->serialSz, |
1335 | 0 | req->heap, DYNAMIC_TYPE_OCSP_REQUEST); |
1336 | 0 | if (req->serial == NULL) |
1337 | 0 | return NULL; |
1338 | 0 | } |
1339 | 0 | XMEMCPY(req->serial, cid->status->serial, (size_t)cid->status->serialSz); |
1340 | 0 | req->serialSz = cid->status->serialSz; |
1341 | |
|
1342 | 0 | return req; |
1343 | 0 | } |
1344 | | |
1345 | | WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id) |
1346 | 0 | { |
1347 | 0 | WOLFSSL_OCSP_CERTID* certId; |
1348 | |
|
1349 | 0 | if (id == NULL) |
1350 | 0 | return NULL; |
1351 | | |
1352 | 0 | certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), |
1353 | 0 | NULL, DYNAMIC_TYPE_OPENSSL); |
1354 | 0 | if (certId) { |
1355 | 0 | XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID)); |
1356 | 0 | } |
1357 | 0 | return certId; |
1358 | 0 | } |
1359 | | |
1360 | | #ifndef NO_BIO |
1361 | | int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, |
1362 | | WOLFSSL_OCSP_REQUEST *req) |
1363 | 0 | { |
1364 | 0 | int size = -1; |
1365 | 0 | unsigned char* data = NULL; |
1366 | |
|
1367 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_OCSP_REQUEST_bio"); |
1368 | 0 | if (out == NULL || req == NULL) |
1369 | 0 | return WOLFSSL_FAILURE; |
1370 | | |
1371 | 0 | size = wolfSSL_i2d_OCSP_REQUEST(req, NULL); |
1372 | 0 | if (size > 0) { |
1373 | 0 | data = (unsigned char*) XMALLOC((size_t)size, out->heap, |
1374 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
1375 | 0 | } |
1376 | |
|
1377 | 0 | if (data != NULL) { |
1378 | 0 | size = wolfSSL_i2d_OCSP_REQUEST(req, &data); |
1379 | 0 | } |
1380 | |
|
1381 | 0 | if (size <= 0) { |
1382 | 0 | XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1383 | 0 | return WOLFSSL_FAILURE; |
1384 | 0 | } |
1385 | | |
1386 | 0 | if (wolfSSL_BIO_write(out, data, size) == (int)size) { |
1387 | 0 | XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1388 | 0 | return WOLFSSL_SUCCESS; |
1389 | 0 | } |
1390 | | |
1391 | 0 | XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1392 | 0 | return WOLFSSL_FAILURE; |
1393 | 0 | } |
1394 | | #endif /* !NO_BIO */ |
1395 | | |
1396 | | int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data) |
1397 | 0 | { |
1398 | 0 | int allocated = 0; |
1399 | 0 | word32 derSz = 0; |
1400 | 0 | word32 intSz = 0; |
1401 | 0 | int ret; |
1402 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_OCSP_CERTID"); |
1403 | |
|
1404 | 0 | if (id == NULL) |
1405 | 0 | return -1; |
1406 | | |
1407 | 0 | if (id->rawCertId != NULL) { |
1408 | 0 | derSz = id->rawCertIdSize; |
1409 | 0 | } |
1410 | 0 | else { |
1411 | 0 | ret = OcspEncodeCertID(id, NULL, &derSz, &intSz); |
1412 | 0 | if (ret != 0) { |
1413 | 0 | WOLFSSL_MSG("Failed to calculate CertID size"); |
1414 | 0 | return -1; |
1415 | 0 | } |
1416 | 0 | } |
1417 | | |
1418 | 0 | if (data == NULL) { |
1419 | 0 | return derSz; |
1420 | 0 | } |
1421 | | |
1422 | 0 | if (*data == NULL) { |
1423 | | /* Allocate buffer for DER encoding */ |
1424 | 0 | *data = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); |
1425 | 0 | if (*data == NULL) { |
1426 | 0 | WOLFSSL_MSG("Failed to allocate memory for CertID DER encoding"); |
1427 | 0 | return -1; |
1428 | 0 | } |
1429 | 0 | allocated = 1; |
1430 | 0 | } |
1431 | | |
1432 | 0 | if (id->rawCertId != NULL) { |
1433 | 0 | XMEMCPY(*data, id->rawCertId, id->rawCertIdSize); |
1434 | 0 | } |
1435 | 0 | else { |
1436 | 0 | ret = OcspEncodeCertID(id, *data, &derSz, &intSz); |
1437 | 0 | if (ret < 0) { |
1438 | 0 | WOLFSSL_MSG("Failed to encode CertID"); |
1439 | 0 | if (allocated) { |
1440 | 0 | XFREE(*data, NULL, DYNAMIC_TYPE_OPENSSL); |
1441 | 0 | *data = NULL; |
1442 | 0 | } |
1443 | 0 | return -1; |
1444 | 0 | } |
1445 | 0 | } |
1446 | | |
1447 | 0 | if (!allocated) |
1448 | 0 | *data += derSz; |
1449 | |
|
1450 | 0 | return derSz; |
1451 | 0 | } |
1452 | | |
1453 | | WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut, |
1454 | | const unsigned char** derIn, |
1455 | | int length) |
1456 | 0 | { |
1457 | 0 | WOLFSSL_OCSP_CERTID *cid = NULL; |
1458 | 0 | int isAllocated = 0; |
1459 | 0 | word32 idx = 0; |
1460 | 0 | int ret; |
1461 | |
|
1462 | 0 | if (derIn == NULL || *derIn == NULL || length <= 0) |
1463 | 0 | return NULL; |
1464 | | |
1465 | 0 | if (cidOut != NULL && *cidOut != NULL) { |
1466 | 0 | cid = *cidOut; |
1467 | 0 | FreeOcspEntry(cid, NULL); |
1468 | 0 | } |
1469 | 0 | else { |
1470 | 0 | cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, |
1471 | 0 | DYNAMIC_TYPE_OPENSSL); |
1472 | 0 | if (cid == NULL) |
1473 | 0 | return NULL; |
1474 | 0 | isAllocated = 1; |
1475 | 0 | } |
1476 | | |
1477 | 0 | XMEMSET(cid, 0, sizeof(WOLFSSL_OCSP_CERTID)); |
1478 | 0 | cid->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, |
1479 | 0 | DYNAMIC_TYPE_OCSP_STATUS); |
1480 | 0 | if (cid->status == NULL) { |
1481 | 0 | XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL); |
1482 | 0 | return NULL; |
1483 | 0 | } |
1484 | 0 | XMEMSET(cid->status, 0, sizeof(CertStatus)); |
1485 | 0 | cid->ownStatus = 1; |
1486 | |
|
1487 | 0 | ret = OcspDecodeCertID(*derIn, &idx, length, cid); |
1488 | 0 | if (ret != 0) { |
1489 | 0 | FreeOcspEntry(cid, NULL); |
1490 | 0 | if (isAllocated) { |
1491 | 0 | XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL); |
1492 | 0 | } |
1493 | 0 | return NULL; |
1494 | 0 | } |
1495 | | |
1496 | 0 | *derIn += idx; |
1497 | |
|
1498 | 0 | if (isAllocated && cidOut != NULL) |
1499 | 0 | *cidOut = cid; |
1500 | |
|
1501 | 0 | return cid; |
1502 | 0 | } |
1503 | | |
1504 | | const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id( |
1505 | | const WOLFSSL_OCSP_SINGLERESP *single) |
1506 | 0 | { |
1507 | 0 | return single; |
1508 | 0 | } |
1509 | | |
1510 | | /** |
1511 | | * Compare two WOLFSSL_OCSP_CERTID objects |
1512 | | * @param a |
1513 | | * @param b |
1514 | | * @return 0 on success and when objects have the same id otherwise either |
1515 | | * the id's don't match or an error occurred |
1516 | | */ |
1517 | | int wolfSSL_OCSP_id_cmp(WOLFSSL_OCSP_CERTID *a, WOLFSSL_OCSP_CERTID *b) |
1518 | 0 | { |
1519 | 0 | int ret = 0; |
1520 | 0 | if (a == NULL || b == NULL) |
1521 | 0 | return WOLFSSL_FATAL_ERROR; |
1522 | | |
1523 | 0 | ret = a->hashAlgoOID != b->hashAlgoOID; |
1524 | 0 | if (ret == 0) |
1525 | 0 | ret = XMEMCMP(a->issuerHash, b->issuerHash, OCSP_DIGEST_SIZE); |
1526 | 0 | if (ret == 0) |
1527 | 0 | ret = XMEMCMP(a->issuerKeyHash, b->issuerKeyHash, OCSP_DIGEST_SIZE); |
1528 | 0 | if (ret == 0) { |
1529 | 0 | if (a->status != NULL && b->status != NULL) { |
1530 | 0 | if (a->status->serialSz == b->status->serialSz) |
1531 | 0 | ret = XMEMCMP(a->status->serial, b->status->serial, |
1532 | 0 | (size_t)a->status->serialSz); |
1533 | 0 | else |
1534 | 0 | ret = -1; |
1535 | 0 | } |
1536 | 0 | else if (a->status != b->status) { |
1537 | | /* If either is not null then return non-zero */ |
1538 | 0 | ret = -1; |
1539 | 0 | } |
1540 | 0 | } |
1541 | 0 | return ret; |
1542 | 0 | } |
1543 | | |
1544 | | int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single, |
1545 | | int *reason, |
1546 | | WOLFSSL_ASN1_TIME **revtime, |
1547 | | WOLFSSL_ASN1_TIME **thisupd, |
1548 | | WOLFSSL_ASN1_TIME **nextupd) |
1549 | 0 | { |
1550 | 0 | if (single == NULL) |
1551 | 0 | return WOLFSSL_FAILURE; |
1552 | | |
1553 | 0 | #ifdef WOLFSSL_OCSP_PARSE_STATUS |
1554 | 0 | if (thisupd != NULL) |
1555 | 0 | *thisupd = &single->status->thisDateParsed; |
1556 | 0 | if (nextupd != NULL) |
1557 | 0 | *nextupd = &single->status->nextDateParsed; |
1558 | | #else |
1559 | | if (thisupd != NULL) |
1560 | | *thisupd = NULL; |
1561 | | if (nextupd != NULL) |
1562 | | *nextupd = NULL; |
1563 | | #endif |
1564 | 0 | if (reason != NULL) |
1565 | 0 | *reason = 0; |
1566 | 0 | if (revtime != NULL) |
1567 | 0 | *revtime = NULL; |
1568 | |
|
1569 | 0 | return single->status->status; |
1570 | 0 | } |
1571 | | |
1572 | | int wolfSSL_OCSP_resp_count(WOLFSSL_OCSP_BASICRESP *bs) |
1573 | 0 | { |
1574 | 0 | WOLFSSL_OCSP_SINGLERESP* single; |
1575 | 0 | int count = 0; |
1576 | |
|
1577 | 0 | if (bs == NULL) |
1578 | 0 | return WOLFSSL_FAILURE; |
1579 | | |
1580 | 0 | single = bs->single; |
1581 | 0 | while(single != NULL) |
1582 | 0 | { |
1583 | 0 | ++count; |
1584 | 0 | single = single->next; |
1585 | 0 | } |
1586 | |
|
1587 | 0 | return count; |
1588 | 0 | } |
1589 | | |
1590 | | WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int idx) |
1591 | 0 | { |
1592 | 0 | WOLFSSL_OCSP_SINGLERESP* single; |
1593 | 0 | int currIdx = 0; |
1594 | |
|
1595 | 0 | if (bs == NULL) |
1596 | 0 | return NULL; |
1597 | | |
1598 | 0 | single = bs->single; |
1599 | 0 | while(single != NULL && currIdx != idx) |
1600 | 0 | { |
1601 | 0 | single = single->next; |
1602 | 0 | ++currIdx; |
1603 | 0 | } |
1604 | |
|
1605 | 0 | return single; |
1606 | 0 | } |
1607 | | |
1608 | | #endif /* OPENSSL_EXTRA */ |
1609 | | |
1610 | | #ifdef OPENSSL_ALL |
1611 | | |
1612 | | /******************************************************************************* |
1613 | | * START OF WOLFSSL_OCSP_REQ_CTX API |
1614 | | ******************************************************************************/ |
1615 | | |
1616 | | enum ocspReqStates { |
1617 | | ORS_INVALID = 0, |
1618 | | ORS_HEADER_ADDED, |
1619 | | ORS_REQ_DONE |
1620 | | }; |
1621 | | |
1622 | | enum ocspReqIOStates { |
1623 | | ORIOS_INVALID = 0, |
1624 | | ORIOS_WRITE, |
1625 | | ORIOS_READ |
1626 | | }; |
1627 | | |
1628 | | WOLFSSL_OCSP_REQ_CTX* wolfSSL_OCSP_REQ_CTX_new(WOLFSSL_BIO *bio, int maxline) |
1629 | 0 | { |
1630 | 0 | WOLFSSL_OCSP_REQ_CTX* ret = NULL; |
1631 | |
|
1632 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_new"); |
1633 | |
|
1634 | 0 | if (maxline <= 0) |
1635 | 0 | maxline = OCSP_MAX_REQUEST_SZ; |
1636 | |
|
1637 | 0 | ret = (WOLFSSL_OCSP_REQ_CTX*)XMALLOC(sizeof(*ret), NULL, |
1638 | 0 | DYNAMIC_TYPE_OPENSSL); |
1639 | 0 | if (ret != NULL) { |
1640 | 0 | XMEMSET(ret, 0, sizeof(*ret)); |
1641 | 0 | ret->buf = (byte*)XMALLOC((word32)maxline, NULL, DYNAMIC_TYPE_OPENSSL); |
1642 | 0 | if (ret->buf == NULL) |
1643 | 0 | goto error; |
1644 | 0 | ret->reqResp = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); |
1645 | 0 | ret->bufLen = maxline; |
1646 | 0 | ret->bio = bio; |
1647 | 0 | ret->ioState = ORIOS_WRITE; |
1648 | 0 | } |
1649 | | |
1650 | 0 | return ret; |
1651 | 0 | error: |
1652 | 0 | wolfSSL_OCSP_REQ_CTX_free(ret); |
1653 | 0 | return NULL; |
1654 | 0 | } |
1655 | | |
1656 | | void wolfSSL_OCSP_REQ_CTX_free(WOLFSSL_OCSP_REQ_CTX *ctx) |
1657 | 0 | { |
1658 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_free"); |
1659 | 0 | if (ctx != NULL) { |
1660 | 0 | if (ctx->buf != NULL) |
1661 | 0 | XFREE(ctx->buf, NULL, DYNAMIC_TYPE_OPENSSL); |
1662 | 0 | if (ctx->reqResp != NULL) |
1663 | 0 | wolfSSL_BIO_free(ctx->reqResp); |
1664 | 0 | XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL); |
1665 | 0 | } |
1666 | 0 | } |
1667 | | |
1668 | | WOLFSSL_OCSP_REQ_CTX* wolfSSL_OCSP_sendreq_new(WOLFSSL_BIO *bio, |
1669 | | const char *path, OcspRequest *req, int maxline) |
1670 | 0 | { |
1671 | 0 | WOLFSSL_OCSP_REQ_CTX* ret = NULL; |
1672 | |
|
1673 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_sendreq_new"); |
1674 | |
|
1675 | 0 | ret = wolfSSL_OCSP_REQ_CTX_new(bio, maxline); |
1676 | 0 | if (ret == NULL) |
1677 | 0 | return NULL; |
1678 | | |
1679 | 0 | if (wolfSSL_OCSP_REQ_CTX_http(ret, "POST", path) != WOLFSSL_SUCCESS) |
1680 | 0 | goto error; |
1681 | | |
1682 | 0 | if (req != NULL && |
1683 | 0 | wolfSSL_OCSP_REQ_CTX_set1_req(ret, req) != WOLFSSL_SUCCESS) |
1684 | 0 | goto error; |
1685 | | |
1686 | 0 | return ret; |
1687 | 0 | error: |
1688 | 0 | wolfSSL_OCSP_REQ_CTX_free(ret); |
1689 | 0 | return NULL; |
1690 | 0 | } |
1691 | | |
1692 | | int wolfSSL_OCSP_REQ_CTX_add1_header(WOLFSSL_OCSP_REQ_CTX *ctx, |
1693 | | const char *name, const char *value) |
1694 | 0 | { |
1695 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_add1_header"); |
1696 | |
|
1697 | 0 | if (name == NULL) { |
1698 | 0 | WOLFSSL_MSG("Bad parameter"); |
1699 | 0 | return WOLFSSL_FAILURE; |
1700 | 0 | } |
1701 | 0 | if (wolfSSL_BIO_puts(ctx->reqResp, name) <= 0) { |
1702 | 0 | WOLFSSL_MSG("wolfSSL_BIO_puts error"); |
1703 | 0 | return WOLFSSL_FAILURE; |
1704 | 0 | } |
1705 | 0 | if (value != NULL) { |
1706 | 0 | if (wolfSSL_BIO_write(ctx->reqResp, ": ", 2) != 2) { |
1707 | 0 | WOLFSSL_MSG("wolfSSL_BIO_write error"); |
1708 | 0 | return WOLFSSL_FAILURE; |
1709 | 0 | } |
1710 | 0 | if (wolfSSL_BIO_puts(ctx->reqResp, value) <= 0) { |
1711 | 0 | WOLFSSL_MSG("wolfSSL_BIO_puts error"); |
1712 | 0 | return WOLFSSL_FAILURE; |
1713 | 0 | } |
1714 | 0 | } |
1715 | 0 | if (wolfSSL_BIO_write(ctx->reqResp, "\r\n", 2) != 2) { |
1716 | 0 | WOLFSSL_MSG("wolfSSL_BIO_write error"); |
1717 | 0 | return WOLFSSL_FAILURE; |
1718 | 0 | } |
1719 | | |
1720 | 0 | ctx->state = ORS_HEADER_ADDED; |
1721 | |
|
1722 | 0 | return WOLFSSL_SUCCESS; |
1723 | 0 | } |
1724 | | |
1725 | | int wolfSSL_OCSP_REQ_CTX_http(WOLFSSL_OCSP_REQ_CTX *ctx, const char *op, |
1726 | | const char *path) |
1727 | 0 | { |
1728 | 0 | static const char http_hdr[] = "%s %s HTTP/1.0\r\n"; |
1729 | |
|
1730 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_http"); |
1731 | |
|
1732 | 0 | if (ctx == NULL || op == NULL) { |
1733 | 0 | WOLFSSL_MSG("Bad parameter"); |
1734 | 0 | return WOLFSSL_FAILURE; |
1735 | 0 | } |
1736 | | |
1737 | 0 | if (path == NULL) |
1738 | 0 | path = "/"; |
1739 | |
|
1740 | 0 | if (wolfSSL_BIO_printf(ctx->reqResp, http_hdr, op, path) <= 0) { |
1741 | 0 | WOLFSSL_MSG("WOLFSSL_OCSP_REQ_CTX: wolfSSL_BIO_printf error"); |
1742 | 0 | return WOLFSSL_FAILURE; |
1743 | 0 | } |
1744 | | |
1745 | 0 | ctx->state = ORS_HEADER_ADDED; |
1746 | |
|
1747 | 0 | return WOLFSSL_SUCCESS; |
1748 | 0 | } |
1749 | | |
1750 | | int wolfSSL_OCSP_REQ_CTX_set1_req(WOLFSSL_OCSP_REQ_CTX *ctx, OcspRequest *req) |
1751 | 0 | { |
1752 | 0 | static const char req_hdr[] = |
1753 | 0 | "Content-Type: application/ocsp-request\r\n" |
1754 | 0 | "Content-Length: %d\r\n\r\n"; |
1755 | | /* Should be enough to hold Content-Length */ |
1756 | 0 | char req_hdr_buf[sizeof(req_hdr) + 10]; |
1757 | 0 | int req_hdr_buf_len; |
1758 | 0 | int req_len = wolfSSL_i2d_OCSP_REQUEST(req, NULL); |
1759 | |
|
1760 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_set1_req"); |
1761 | |
|
1762 | 0 | if (ctx == NULL || req == NULL) { |
1763 | 0 | WOLFSSL_MSG("Bad parameters"); |
1764 | 0 | return WOLFSSL_FAILURE; |
1765 | 0 | } |
1766 | | |
1767 | 0 | if (req_len <= 0) { |
1768 | 0 | WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request len error"); |
1769 | 0 | return WOLFSSL_FAILURE; |
1770 | 0 | } |
1771 | | |
1772 | 0 | req_hdr_buf_len = |
1773 | 0 | XSNPRINTF(req_hdr_buf, sizeof(req_hdr_buf), req_hdr, req_len); |
1774 | 0 | if (req_hdr_buf_len >= (int)sizeof(req_hdr_buf)) { |
1775 | 0 | WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request too long"); |
1776 | 0 | return WOLFSSL_FAILURE; |
1777 | 0 | } |
1778 | | |
1779 | 0 | if (wolfSSL_BIO_write(ctx->reqResp, req_hdr_buf, req_hdr_buf_len) <= 0) { |
1780 | 0 | WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: wolfSSL_BIO_write error"); |
1781 | 0 | return WOLFSSL_FAILURE; |
1782 | 0 | } |
1783 | | |
1784 | 0 | if (wolfSSL_i2d_OCSP_REQUEST_bio(ctx->reqResp, req) <= 0) { |
1785 | 0 | WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request i2d error"); |
1786 | 0 | return WOLFSSL_FAILURE; |
1787 | 0 | } |
1788 | | |
1789 | 0 | ctx->state = ORS_REQ_DONE; |
1790 | |
|
1791 | 0 | return WOLFSSL_SUCCESS; |
1792 | 0 | } |
1793 | | |
1794 | | static int OCSP_REQ_CTX_bio_cb(char *buf, int sz, void *ctx) |
1795 | 0 | { |
1796 | 0 | return BioReceiveInternal((WOLFSSL_BIO*)ctx, NULL, buf, sz); |
1797 | 0 | } |
1798 | | |
1799 | | int wolfSSL_OCSP_REQ_CTX_nbio(WOLFSSL_OCSP_REQ_CTX *ctx) |
1800 | 0 | { |
1801 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_nbio"); |
1802 | |
|
1803 | 0 | if (ctx == NULL) { |
1804 | 0 | WOLFSSL_MSG("Bad parameters"); |
1805 | 0 | return WOLFSSL_FAILURE; |
1806 | 0 | } |
1807 | | |
1808 | 0 | switch ((enum ocspReqIOStates)ctx->ioState) { |
1809 | 0 | case ORIOS_WRITE: |
1810 | 0 | case ORIOS_READ: |
1811 | 0 | break; |
1812 | 0 | case ORIOS_INVALID: |
1813 | 0 | default: |
1814 | 0 | WOLFSSL_MSG("Invalid ctx->ioState state"); |
1815 | 0 | return WOLFSSL_FAILURE; |
1816 | 0 | } |
1817 | | |
1818 | 0 | if (ctx->ioState == ORIOS_WRITE) { |
1819 | 0 | switch ((enum ocspReqStates)ctx->state) { |
1820 | 0 | case ORS_HEADER_ADDED: |
1821 | | /* Write final new line to complete http header */ |
1822 | 0 | if (wolfSSL_BIO_write(ctx->reqResp, "\r\n", 2) != 2) { |
1823 | 0 | WOLFSSL_MSG("wolfSSL_BIO_write error"); |
1824 | 0 | return WOLFSSL_FAILURE; |
1825 | 0 | } |
1826 | 0 | break; |
1827 | 0 | case ORS_REQ_DONE: |
1828 | 0 | break; |
1829 | 0 | case ORS_INVALID: |
1830 | 0 | default: |
1831 | 0 | WOLFSSL_MSG("Invalid WOLFSSL_OCSP_REQ_CTX state"); |
1832 | 0 | return WOLFSSL_FAILURE; |
1833 | 0 | } |
1834 | 0 | } |
1835 | | |
1836 | 0 | switch ((enum ocspReqIOStates)ctx->ioState) { |
1837 | 0 | case ORIOS_WRITE: |
1838 | 0 | { |
1839 | 0 | const unsigned char *req; |
1840 | 0 | int reqLen = wolfSSL_BIO_get_mem_data(ctx->reqResp, (void*)&req); |
1841 | 0 | if (reqLen <= 0) { |
1842 | 0 | WOLFSSL_MSG("wolfSSL_BIO_get_mem_data error"); |
1843 | 0 | return WOLFSSL_FAILURE; |
1844 | 0 | } |
1845 | 0 | while (ctx->sent < reqLen) { |
1846 | 0 | int sent = wolfSSL_BIO_write(ctx->bio, req + ctx->sent, |
1847 | 0 | reqLen - ctx->sent); |
1848 | 0 | if (sent <= 0) { |
1849 | 0 | if (wolfSSL_BIO_should_retry(ctx->bio)) |
1850 | 0 | return WOLFSSL_FATAL_ERROR; |
1851 | 0 | WOLFSSL_MSG("wolfSSL_BIO_write error"); |
1852 | 0 | ctx->ioState = ORIOS_INVALID; |
1853 | 0 | return 0; |
1854 | 0 | } |
1855 | 0 | ctx->sent += sent; |
1856 | 0 | } |
1857 | 0 | ctx->sent = 0; |
1858 | 0 | ctx->ioState = ORIOS_READ; |
1859 | 0 | (void)wolfSSL_BIO_reset(ctx->reqResp); |
1860 | 0 | FALL_THROUGH; |
1861 | 0 | } |
1862 | 0 | case ORIOS_READ: |
1863 | 0 | { |
1864 | 0 | byte* resp = NULL; |
1865 | 0 | int respLen; |
1866 | 0 | int ret; |
1867 | |
|
1868 | 0 | if (ctx->buf == NULL) /* Should be allocated in new call */ |
1869 | 0 | return WOLFSSL_FAILURE; |
1870 | | |
1871 | 0 | ret = wolfIO_HttpProcessResponseOcspGenericIO(OCSP_REQ_CTX_bio_cb, |
1872 | 0 | ctx->bio, &resp, ctx->buf, ctx->bufLen, NULL); |
1873 | 0 | if (ret <= 0) { |
1874 | 0 | if (resp != NULL) |
1875 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP); |
1876 | 0 | if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) || |
1877 | 0 | ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) |
1878 | 0 | { |
1879 | 0 | return WOLFSSL_FATAL_ERROR; |
1880 | 0 | } |
1881 | 0 | return WOLFSSL_FAILURE; |
1882 | 0 | } |
1883 | 0 | respLen = ret; |
1884 | 0 | ret = wolfSSL_BIO_write(ctx->reqResp, resp, respLen); |
1885 | 0 | XFREE(resp, NULL, DYNAMIC_TYPE_OCSP); |
1886 | 0 | if (ret != respLen) { |
1887 | 0 | WOLFSSL_MSG("wolfSSL_BIO_write error"); |
1888 | 0 | return WOLFSSL_FAILURE; |
1889 | 0 | } |
1890 | 0 | break; |
1891 | 0 | } |
1892 | 0 | case ORIOS_INVALID: |
1893 | 0 | default: |
1894 | 0 | WOLFSSL_MSG("Invalid ctx->ioState state"); |
1895 | 0 | return WOLFSSL_FAILURE; |
1896 | 0 | } |
1897 | | |
1898 | 0 | return WOLFSSL_SUCCESS; |
1899 | 0 | } |
1900 | | |
1901 | | int wolfSSL_OCSP_sendreq_nbio(OcspResponse **presp, WOLFSSL_OCSP_REQ_CTX *ctx) |
1902 | 0 | { |
1903 | 0 | int ret; |
1904 | 0 | int len; |
1905 | 0 | const unsigned char *resp = NULL; |
1906 | |
|
1907 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_sendreq_nbio"); |
1908 | |
|
1909 | 0 | if (presp == NULL) |
1910 | 0 | return WOLFSSL_FAILURE; |
1911 | | |
1912 | 0 | ret = wolfSSL_OCSP_REQ_CTX_nbio(ctx); |
1913 | 0 | if (ret != WOLFSSL_SUCCESS) |
1914 | 0 | return ret; |
1915 | | |
1916 | 0 | len = wolfSSL_BIO_get_mem_data(ctx->reqResp, (void*)&resp); |
1917 | 0 | if (len <= 0) |
1918 | 0 | return WOLFSSL_FAILURE; |
1919 | 0 | return wolfSSL_d2i_OCSP_RESPONSE(presp, &resp, len) != NULL |
1920 | 0 | ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; |
1921 | 0 | } |
1922 | | |
1923 | | /******************************************************************************* |
1924 | | * END OF WOLFSSL_OCSP_REQ_CTX API |
1925 | | ******************************************************************************/ |
1926 | | |
1927 | | #ifndef NO_WOLFSSL_STUB |
1928 | | int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext, |
1929 | | int idx) |
1930 | 0 | { |
1931 | 0 | WOLFSSL_STUB("wolfSSL_OCSP_REQUEST_add_ext"); |
1932 | 0 | (void)req; |
1933 | 0 | (void)ext; |
1934 | 0 | (void)idx; |
1935 | 0 | return WOLFSSL_FATAL_ERROR; |
1936 | 0 | } |
1937 | | #endif |
1938 | | |
1939 | | #ifndef NO_WOLFSSL_STUB |
1940 | | OcspResponse* wolfSSL_OCSP_response_create(int status, |
1941 | | WOLFSSL_OCSP_BASICRESP* bs) |
1942 | 0 | { |
1943 | 0 | WOLFSSL_STUB("wolfSSL_OCSP_response_create"); |
1944 | 0 | (void)status; |
1945 | 0 | (void)bs; |
1946 | 0 | return NULL; |
1947 | 0 | } |
1948 | | #endif |
1949 | | |
1950 | | #ifndef NO_WOLFSSL_STUB |
1951 | | const char* wolfSSL_OCSP_crl_reason_str(long s) |
1952 | 0 | { |
1953 | 0 | WOLFSSL_STUB("wolfSSL_OCSP_crl_reason_str"); |
1954 | 0 | (void)s; |
1955 | 0 | return NULL; |
1956 | 0 | } |
1957 | | #endif |
1958 | | |
1959 | | /* Returns elements of an OCSP_CERTID struct. Currently only supports |
1960 | | * returning the serial number, and returns an error if user requests |
1961 | | * any of name, pmd, and/or keyHash. |
1962 | | * Return 1 on success, 0 on failure */ |
1963 | | int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, |
1964 | | WOLFSSL_ASN1_OBJECT **pmd, WOLFSSL_ASN1_STRING **keyHash, |
1965 | | WOLFSSL_ASN1_INTEGER **serial, WOLFSSL_OCSP_CERTID *cid) |
1966 | 0 | { |
1967 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_id_get0_info"); |
1968 | |
|
1969 | 0 | if (cid == NULL) |
1970 | 0 | return 0; |
1971 | | |
1972 | | /* build up ASN1_INTEGER for serial */ |
1973 | 0 | if (serial != NULL) { |
1974 | 0 | int i = 0; |
1975 | 0 | WOLFSSL_ASN1_INTEGER* ser; |
1976 | |
|
1977 | 0 | ser = wolfSSL_ASN1_INTEGER_new(); |
1978 | 0 | if (ser == NULL) |
1979 | 0 | return 0; |
1980 | | |
1981 | 0 | if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { |
1982 | | /* allocate data buffer, +2 for type and length */ |
1983 | 0 | ser->data = (unsigned char*)XMALLOC((size_t)cid->status->serialSz + 2, NULL, |
1984 | 0 | DYNAMIC_TYPE_OPENSSL); |
1985 | 0 | if (ser->data == NULL) { |
1986 | 0 | wolfSSL_ASN1_INTEGER_free(ser); |
1987 | 0 | return 0; |
1988 | 0 | } |
1989 | 0 | ser->dataMax = (unsigned int)cid->status->serialSz + 2; |
1990 | 0 | ser->isDynamic = 1; |
1991 | 0 | } else { |
1992 | | /* Use array instead of dynamic memory */ |
1993 | 0 | ser->data = ser->intData; |
1994 | 0 | ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX; |
1995 | 0 | } |
1996 | | |
1997 | | #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) |
1998 | | /* Serial number starts at 0 index of ser->data */ |
1999 | | XMEMCPY(&ser->data[i], cid->status->serial, |
2000 | | (size_t)cid->status->serialSz); |
2001 | | ser->length = cid->status->serialSz; |
2002 | | #else |
2003 | 0 | ser->data[i++] = ASN_INTEGER; |
2004 | 0 | i += SetLength(cid->status->serialSz, ser->data + i); |
2005 | 0 | XMEMCPY(&ser->data[i], cid->status->serial, |
2006 | 0 | (size_t)cid->status->serialSz); |
2007 | 0 | ser->length = i + cid->status->serialSz; |
2008 | 0 | #endif |
2009 | |
|
2010 | 0 | cid->status->serialInt = ser; |
2011 | 0 | *serial = ser; |
2012 | 0 | } |
2013 | | |
2014 | | /* Not needed for Apache, return error if user is requesting */ |
2015 | 0 | if (name != NULL || pmd != NULL || keyHash != NULL) { |
2016 | 0 | if (name != NULL) |
2017 | 0 | *name = NULL; |
2018 | |
|
2019 | 0 | if (pmd != NULL) |
2020 | 0 | *pmd = NULL; |
2021 | |
|
2022 | 0 | if (keyHash != NULL) |
2023 | 0 | *keyHash = NULL; |
2024 | 0 | return 0; |
2025 | 0 | } |
2026 | | |
2027 | 0 | return 1; |
2028 | 0 | } |
2029 | | |
2030 | | int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val, |
2031 | | int sz) |
2032 | 0 | { |
2033 | 0 | WC_RNG rng; |
2034 | |
|
2035 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_request_add1_nonce"); |
2036 | |
|
2037 | 0 | if (req == NULL || sz > MAX_OCSP_NONCE_SZ) { |
2038 | 0 | WOLFSSL_MSG("Bad parameter"); |
2039 | 0 | return WOLFSSL_FAILURE; |
2040 | 0 | } |
2041 | | |
2042 | 0 | if (sz <= 0) |
2043 | 0 | sz = MAX_OCSP_NONCE_SZ; |
2044 | |
|
2045 | 0 | if (val != NULL) { |
2046 | 0 | XMEMCPY(req->nonce, val, (size_t)sz); |
2047 | 0 | } |
2048 | 0 | else { |
2049 | 0 | if ( |
2050 | 0 | #ifndef HAVE_FIPS |
2051 | 0 | wc_InitRng_ex(&rng, req->heap, INVALID_DEVID) |
2052 | | #else |
2053 | | wc_InitRng(&rng) |
2054 | | #endif |
2055 | 0 | != 0) { |
2056 | 0 | WOLFSSL_MSG("RNG init failed"); |
2057 | 0 | return WOLFSSL_FAILURE; |
2058 | 0 | } |
2059 | 0 | if (wc_RNG_GenerateBlock(&rng, req->nonce, (word32)sz) != 0) { |
2060 | 0 | WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); |
2061 | 0 | wc_FreeRng(&rng); |
2062 | 0 | return WOLFSSL_FAILURE; |
2063 | 0 | } |
2064 | 0 | wc_FreeRng(&rng); |
2065 | 0 | } |
2066 | 0 | req->nonceSz = sz; |
2067 | |
|
2068 | 0 | return WOLFSSL_SUCCESS; |
2069 | 0 | } |
2070 | | |
2071 | | /* Returns result of OCSP nonce comparison. Return values: |
2072 | | * 1 - nonces are both present and equal |
2073 | | * 2 - both nonces are absent |
2074 | | * 3 - nonce only present in response |
2075 | | * -1 - nonce only present in request |
2076 | | * 0 - both nonces present and equal |
2077 | | */ |
2078 | | int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs) |
2079 | 0 | { |
2080 | 0 | byte* reqNonce = NULL; |
2081 | 0 | byte* rspNonce = NULL; |
2082 | 0 | int reqNonceSz = 0; |
2083 | 0 | int rspNonceSz = 0; |
2084 | |
|
2085 | 0 | WOLFSSL_ENTER("wolfSSL_OCSP_check_nonce"); |
2086 | |
|
2087 | 0 | if (req != NULL) { |
2088 | 0 | reqNonce = req->nonce; |
2089 | 0 | reqNonceSz = req->nonceSz; |
2090 | 0 | } |
2091 | |
|
2092 | 0 | if (bs != NULL) { |
2093 | 0 | rspNonce = bs->nonce; |
2094 | 0 | rspNonceSz = bs->nonceSz; |
2095 | 0 | } |
2096 | | |
2097 | | /* nonce absent in both req and rsp */ |
2098 | 0 | if (reqNonce == NULL && rspNonce == NULL) |
2099 | 0 | return 2; |
2100 | | |
2101 | | /* nonce present in rsp only */ |
2102 | 0 | if (reqNonce == NULL && rspNonce != NULL) |
2103 | 0 | return 3; |
2104 | | |
2105 | | /* nonce present in req only */ |
2106 | 0 | if (reqNonce != NULL && rspNonce == NULL) |
2107 | 0 | return WOLFSSL_FATAL_ERROR; |
2108 | | |
2109 | | /* nonces are present and equal, return 1. Extra NULL check for fixing |
2110 | | scan-build warning. */ |
2111 | 0 | if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) { |
2112 | 0 | if (XMEMCMP(reqNonce, rspNonce, (size_t)reqNonceSz) == 0) |
2113 | 0 | return 1; |
2114 | 0 | } |
2115 | | |
2116 | | /* nonces are present but not equal */ |
2117 | 0 | return 0; |
2118 | 0 | } |
2119 | | |
2120 | | #endif /* OPENSSL_ALL */ |
2121 | | |
2122 | | #else /* HAVE_OCSP */ |
2123 | | |
2124 | | |
2125 | | #ifdef _MSC_VER |
2126 | | /* 4206 warning for blank file */ |
2127 | | #pragma warning(disable: 4206) |
2128 | | #endif |
2129 | | |
2130 | | |
2131 | | #endif /* HAVE_OCSP */ |
2132 | | #endif /* WOLFCRYPT_ONLY */ |