ocsp_client.c
Go to the documentation of this file.
1 /**
2  * @file ocsp_client.c
3  * @brief OCSP client
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * OCSP is a protocol used to determine the current status of a digital
30  * certificate without requiring CRLs. Refer to the following RFCs for
31  * complete details:
32  * - RFC 6960: X.509 Internet Public Key Infrastructure OCSP
33  * - RFC 8954: Online Certificate Status Protocol (OCSP) Nonce Extension
34  *
35  * @author Oryx Embedded SARL (www.oryx-embedded.com)
36  * @version 2.5.4
37  **/
38 
39 //Switch to the appropriate trace level
40 #define TRACE_LEVEL OCSP_TRACE_LEVEL
41 
42 //Dependencies
43 #include "ocsp/ocsp_client.h"
44 #include "ocsp/ocsp_client_misc.h"
45 #include "ocsp/ocsp_resp_parse.h"
47 #include "pkix/pem_import.h"
48 #include "pkix/x509_cert_parse.h"
49 #include "debug.h"
50 
51 //Check crypto library configuration
52 #if (OCSP_CLIENT_SUPPORT == ENABLED)
53 
54 
55 /**
56  * @brief OCSP client initialization
57  * @param[in] context Pointer to the OCSP client context
58  * @return Error code
59  **/
60 
62 {
63  error_t error;
64 
65  //Make sure the OCSP client context is valid
66  if(context == NULL)
68 
69  //Debug message
70  TRACE_INFO("Initializing OCSP client...\r\n");
71 
72  //Initialize context
73  osMemset(context, 0, sizeof(OcspClientContext));
74 
75  //Initialize HTTP client context
76  error = httpClientInit(&context->httpClientContext);
77  //Any error to report?
78  if(error)
79  return error;
80 
81  //Initialize OCSP client state
82  context->state = OCSP_CLIENT_STATE_DISCONNECTED;
83 
84  //Default timeout
85  context->timeout = OCSP_CLIENT_DEFAULT_TIMEOUT;
86  //Default URI
87  osStrcpy(context->uri, "/");
88 
89  //Successful initialization
90  return NO_ERROR;
91 }
92 
93 
94 #if (OCSP_CLIENT_TLS_SUPPORT == ENABLED)
95 
96 /**
97  * @brief Register TLS initialization callback function
98  * @param[in] context Pointer to the OCSP client context
99  * @param[in] callback TLS initialization callback function
100  * @return Error code
101  **/
102 
104  OcspClientTlsInitCallback callback)
105 {
106  //Make sure the OCSP client context is valid
107  if(context == NULL)
109 
110  //Save callback function
111  context->tlsInitCallback = callback;
112 
113  //Successful processing
114  return NO_ERROR;
115 }
116 
117 #endif
118 
119 
120 /**
121  * @brief Set the pseudo-random number generator to be used
122  * @param[in] context Pointer to the OCSP client context
123  * @param[in] prngAlgo PRNG algorithm
124  * @param[in] prngContext Pointer to the PRNG context
125  * @return Error code
126  **/
127 
129  void *prngContext)
130 {
131  //Check parameters
132  if(context == NULL || prngAlgo == NULL || prngContext == NULL)
134 
135  //PRNG algorithm that will be used to generate nonces
136  context->prngAlgo = prngAlgo;
137  //PRNG context
138  context->prngContext = prngContext;
139 
140  //Successful processing
141  return NO_ERROR;
142 }
143 
144 
145 /**
146  * @brief Set communication timeout
147  * @param[in] context Pointer to the OCSP client context
148  * @param[in] timeout Timeout value, in milliseconds
149  * @return Error code
150  **/
151 
153 {
154  //Make sure the OCSP client context is valid
155  if(context == NULL)
157 
158  //Save timeout value
159  context->timeout = timeout;
160 
161  //Successful processing
162  return NO_ERROR;
163 }
164 
165 
166 /**
167  * @brief Set the domain name of the OCSP server
168  * @param[in] context Pointer to the OCSP client context
169  * @param[in] host NULL-terminated string containing the host name
170  * @return Error code
171  **/
172 
174 {
175  //Check parameters
176  if(context == NULL || host == NULL)
178 
179  //Make sure the length of the host name is acceptable
181  return ERROR_INVALID_LENGTH;
182 
183  //Save host name
184  osStrcpy(context->serverName, host);
185 
186  //Successful processing
187  return NO_ERROR;
188 }
189 
190 
191 /**
192  * @brief Set request URI
193  * @param[in] context Pointer to the OCSP client context
194  * @param[in] uri NULL-terminated string that contains the resource name
195  * @return Error code
196  **/
197 
199 {
200  //Check parameters
201  if(context == NULL || uri == NULL)
203 
204  //Make sure the length of the URI is acceptable
206  return ERROR_INVALID_LENGTH;
207 
208  //Save the URI of the directory object
209  osStrcpy(context->uri, uri);
210 
211  //Successful processing
212  return NO_ERROR;
213 }
214 
215 /**
216  * @brief Bind the OCSP client to a particular network interface
217  * @param[in] context Pointer to the OCSP client context
218  * @param[in] interface Network interface to be used
219  * @return Error code
220  **/
221 
223  NetInterface *interface)
224 {
225  //Make sure the OCSP client context is valid
226  if(context == NULL)
228 
229  //Explicitly associate the OCSP client with the specified interface
230  context->interface = interface;
231 
232  //Successful processing
233  return NO_ERROR;
234 }
235 
236 
237 /**
238  * @brief Specify the address of the OCSP server
239  * @param[in] context Pointer to the OCSP client context
240  * @param[in] serverIpAddr IP address of the OCSP server to connect to
241  * @param[in] serverPort UDP port number
242  * @return Error code
243  **/
244 
246  const IpAddr *serverIpAddr, uint16_t serverPort)
247 {
248  error_t error;
249 
250  //Make sure the OCSP client context is valid
251  if(context == NULL)
253 
254  //Initialize status code
255  error = NO_ERROR;
256 
257  //Establish connection with the HTTP server
258  while(!error)
259  {
260  //Check OCSP client state
261  if(context->state == OCSP_CLIENT_STATE_DISCONNECTED)
262  {
263  //Save the TCP port number to be used
264  context->serverPort = serverPort;
265 
266 #if (OCSP_CLIENT_TLS_SUPPORT == ENABLED)
267  //Where privacy is a requirement, OCSP transactions exchanged using
268  //HTTP may be protected using either TLS/SSL or some other lower layer
269  //protocol (refer to RFC 6960, appendix A.1)
270  if(context->tlsInitCallback != NULL)
271  {
272  //Register TLS initialization callback
273  error = httpClientRegisterTlsInitCallback(&context->httpClientContext,
274  ocspClientInitTlsContext, context);
275  }
276 #endif
277  //Check status code
278  if(!error)
279  {
280  //Select HTTP protocol version
281  error = httpClientSetVersion(&context->httpClientContext,
283  }
284 
285  //Check status code
286  if(!error)
287  {
288  //Set timeout value for blocking operations
289  error = httpClientSetTimeout(&context->httpClientContext,
290  context->timeout);
291  }
292 
293  //Check status code
294  if(!error)
295  {
296  //Bind the HTTP client to the relevant network interface
297  error = httpClientBindToInterface(&context->httpClientContext,
298  context->interface);
299  }
300 
301  //Check status code
302  if(!error)
303  {
304  //Establish HTTP connection
305  context->state = OCSP_CLIENT_STATE_CONNECTING;
306  }
307  }
308  else if(context->state == OCSP_CLIENT_STATE_CONNECTING)
309  {
310  //Establish HTTP connection
311  error = httpClientConnect(&context->httpClientContext, serverIpAddr,
312  serverPort);
313 
314  //Check status code
315  if(error == NO_ERROR)
316  {
317  //The HTTP connection is established
318  context->state = OCSP_CLIENT_STATE_CONNECTED;
319  }
320  }
321  else if(context->state == OCSP_CLIENT_STATE_CONNECTED)
322  {
323  //The client is connected to the OCSP server
324  break;
325  }
326  else
327  {
328  //Invalid state
329  error = ERROR_WRONG_STATE;
330  }
331  }
332 
333  //Failed to establish connection with the OCSP server?
334  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
335  {
336  //Clean up side effects
337  httpClientClose(&context->httpClientContext);
338  //Update OCSP client state
339  context->state = OCSP_CLIENT_STATE_DISCONNECTED;
340  }
341 
342  //Return status code
343  return error;
344 }
345 
346 
347 /**
348  * @brief Create OCSP request
349  * @param[in] context Pointer to the OCSP client context
350  * @param[in] cert Certificate to be checked (PEM or DER format)
351  * @param[in] certLen Length of the certificate, in bytes
352  * @param[in] issuerCert Issuer's certificate (PEM or DER format)
353  * @param[in] issuerCertLen Length of the issuer certificate, in bytes
354  * @return Error code
355  **/
356 
358  const char_t *cert, size_t certLen, const char_t *issuerCert,
359  size_t issuerCertLen)
360 {
361  error_t error;
362 
363  //Check parameters
364  if(context == NULL || cert == NULL || issuerCert == NULL)
366 
367  //Check OCSP client state
368  if(context->state != OCSP_CLIENT_STATE_CONNECTED &&
369  context->state != OCSP_CLIENT_STATE_PARSE_RESP &&
370  context->state != OCSP_CLIENT_STATE_VALIDATE_RESP &&
371  context->state != OCSP_CLIENT_STATE_RESP_VALIDATED)
372  {
373  return ERROR_WRONG_STATE;
374  }
375 
376  //The value of the nonce must be generated using a cryptographically strong
377  //pseudorandom number generator
378  error = ocspClientGenerateNonce(context);
379  //Any error to report?
380  if(error)
381  return error;
382 
383  //Format OCSP request
384  error = ocspClientFormatRequest(context, cert, certLen, issuerCert,
385  issuerCertLen);
386  //Any error to report?
387  if(error)
388  return error;
389 
390  //Update OCSP client state
391  context->state = OCSP_CLIENT_STATE_FORMAT_HEADER;
392 
393  //Successful processing
394  return NO_ERROR;
395 }
396 
397 
398 /**
399  * @brief Perform OCSP request/response transaction
400  * @param[in] context Pointer to the OCSP client context
401  * @return Error code
402  **/
403 
405 {
406  error_t error;
407  size_t n;
408 
409  //Make sure the OCSP client context is valid
410  if(context == NULL)
412 
413  //Initialize status code
414  error = NO_ERROR;
415 
416  //Perform HTTP request
417  while(!error)
418  {
419  //Check OCSP client state
420  if(context->state == OCSP_CLIENT_STATE_FORMAT_HEADER)
421  {
422  //Format HTTP request header
423  error = ocspClientFormatHeader(context);
424 
425  //Check status code
426  if(!error)
427  {
428  //Update OCSP client state
429  context->state = OCSP_CLIENT_STATE_SEND_HEADER;
430  }
431  }
432  else if(context->state == OCSP_CLIENT_STATE_SEND_HEADER)
433  {
434  //Send HTTP request header
435  error = httpClientWriteHeader(&context->httpClientContext);
436 
437  //Check status code
438  if(!error)
439  {
440  //Point to the first byte of the body
441  context->bufferPos = 0;
442 
443  //Update OCSP client state
444  context->state = OCSP_CLIENT_STATE_SEND_BODY;
445  }
446  }
447  else if(context->state == OCSP_CLIENT_STATE_SEND_BODY)
448  {
449  //Send HTTP request body
450  if(context->bufferPos < context->bufferLen)
451  {
452  //Send more data
453  error = httpClientWriteBody(&context->httpClientContext,
454  context->buffer + context->bufferPos,
455  context->bufferLen - context->bufferPos, &n, 0);
456 
457  //Check status code
458  if(!error)
459  {
460  //Advance data pointer
461  context->bufferPos += n;
462  }
463  }
464  else
465  {
466  //Update HTTP request state
467  context->state = OCSP_CLIENT_STATE_RECEIVE_HEADER;
468  }
469  }
470  else if(context->state == OCSP_CLIENT_STATE_RECEIVE_HEADER)
471  {
472  //Receive HTTP response header
473  error = httpClientReadHeader(&context->httpClientContext);
474 
475  //Check status code
476  if(!error)
477  {
478  //Update OCSP client state
479  context->state = OCSP_CLIENT_STATE_PARSE_HEADER;
480  }
481  }
482  else if(context->state == OCSP_CLIENT_STATE_PARSE_HEADER)
483  {
484  //Parse HTTP response header
485  error = ocspClientParseHeader(context);
486 
487  //Check status code
488  if(!error)
489  {
490  //Flush the receive buffer
491  context->bufferLen = 0;
492  context->bufferPos = 0;
493 
494  //Update OCSP client state
495  context->state = OCSP_CLIENT_STATE_RECEIVE_BODY;
496  }
497  }
498  else if(context->state == OCSP_CLIENT_STATE_RECEIVE_BODY)
499  {
500  //Receive HTTP response body
501  if(context->bufferLen < OCSP_CLIENT_BUFFER_SIZE)
502  {
503  //Receive more data
504  error = httpClientReadBody(&context->httpClientContext,
505  context->buffer + context->bufferLen,
506  OCSP_CLIENT_BUFFER_SIZE - context->bufferLen, &n, 0);
507 
508  //Check status code
509  if(error == NO_ERROR)
510  {
511  //Advance data pointer
512  context->bufferLen += n;
513  }
514  else if(error == ERROR_END_OF_STREAM)
515  {
516  //The end of the response body has been reached
517  error = NO_ERROR;
518 
519  //Update OCSP client state
520  context->state = OCSP_CLIENT_STATE_CLOSE_BODY;
521  }
522  else
523  {
524  //Just for sanity
525  }
526  }
527  else
528  {
529  //Update OCSP client state
530  context->state = OCSP_CLIENT_STATE_CLOSE_BODY;
531  }
532  }
533  else if(context->state == OCSP_CLIENT_STATE_CLOSE_BODY)
534  {
535  //Close HTTP response body
536  error = httpClientCloseBody(&context->httpClientContext);
537 
538  //Check status code
539  if(!error)
540  {
541  //Update OCSP client state
542  context->state = OCSP_CLIENT_STATE_PARSE_RESP;
543  }
544  }
545  else if(context->state == OCSP_CLIENT_STATE_PARSE_RESP)
546  {
547  //Parse OCSP response
548  error = ocspParseResponse(context->buffer, context->bufferLen,
549  &context->ocspResponse);
550 
551  //Check status code
552  if(!error)
553  {
554  //Update OCSP client state
555  context->state = OCSP_CLIENT_STATE_VALIDATE_RESP;
556  break;
557  }
558  }
559  else
560  {
561  //Invalid state
562  error = ERROR_WRONG_STATE;
563  }
564  }
565 
566  //Return status code
567  return error;
568 }
569 
570 
571 /**
572  * @brief Validate OCSP response
573  * @param[in] context Pointer to the OCSP client context
574  * @param[in] cert Certificate to be checked (PEM or DER format)
575  * @param[in] certLen Length of the certificate, in bytes
576  * @param[in] issuerCert Issuer's certificate (PEM or DER format)
577  * @param[in] issuerCertLen Length of the issuer certificate, in bytes
578  * @return Error code
579  **/
580 
582  const char_t *cert, size_t certLen, const char_t *issuerCert,
583  size_t issuerCertLen)
584 {
585  error_t error;
586  uint8_t *derCert;
587  size_t derCertLen;
588  uint8_t *derIssuerCert;
589  size_t derIssuerCertLen;
590  X509CertInfo *certInfo;
591  X509CertInfo *issuerCertInfo;
593 
594  //Check parameters
595  if(context == NULL || cert == NULL || issuerCert == NULL)
597 
598  //Check OCSP client state
599  if(context->state != OCSP_CLIENT_STATE_VALIDATE_RESP)
600  return ERROR_WRONG_STATE;
601 
602  //Check response status
603  if(context->ocspResponse.responseStatus != OCSP_RESP_STATUS_SUCCESSFUL)
605 
606  //Initialize variables
607  derCert = NULL;
608  derIssuerCert = NULL;
609  certInfo = NULL;
610  issuerCertInfo = NULL;
611 
612  //Additional certificate parsing options
614  options.ignoreUnknownExtensions = TRUE;
615 
616  //Start of exception handling block
617  do
618  {
619  //Allocate a memory buffer to store X.509 certificate info
620  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
621  //Failed to allocate memory?
622  if(certInfo == NULL)
623  {
624  error = ERROR_OUT_OF_MEMORY;
625  break;
626  }
627 
628  //The OCSP client accepts certificates in either PEM or DER format
629  error = pemImportCertificate(cert, certLen, NULL, &derCertLen, NULL);
630 
631  //PEM or DER format?
632  if(!error)
633  {
634  //Allocate a memory buffer to hold the DER-encoded certificate
635  derCert = cryptoAllocMem(derCertLen);
636  //Failed to allocate memory?
637  if(derCert == NULL)
638  {
639  error = ERROR_OUT_OF_MEMORY;
640  break;
641  }
642 
643  //The second pass decodes the PEM certificate
644  error = pemImportCertificate(cert, certLen, derCert, &derCertLen,
645  NULL);
646  //Any error to report?
647  if(error)
648  break;
649 
650  //Parse X.509 certificate
651  error = x509ParseCertificateEx(derCert, derCertLen, certInfo,
652  &options);
653  //Any error to report?
654  if(error)
655  break;
656  }
657  else
658  {
659  //Parse X.509 certificate
660  error = x509ParseCertificateEx(cert, certLen, certInfo, &options);
661  //Any error to report?
662  if(error)
663  break;
664  }
665 
666  //Allocate a memory buffer to store X.509 certificate info
667  issuerCertInfo = cryptoAllocMem(sizeof(X509CertInfo));
668  //Failed to allocate memory?
669  if(certInfo == NULL)
670  {
671  error = ERROR_OUT_OF_MEMORY;
672  break;
673  }
674 
675  //The OCSP client accepts certificates in either PEM or DER format
676  error = pemImportCertificate(issuerCert, issuerCertLen, NULL,
677  &derIssuerCertLen, NULL);
678 
679  //PEM or DER format?
680  if(!error)
681  {
682  //Allocate a memory buffer to hold the DER-encoded certificate
683  derIssuerCert = cryptoAllocMem(derIssuerCertLen);
684  //Failed to allocate memory?
685  if(derCert == NULL)
686  {
687  error = ERROR_OUT_OF_MEMORY;
688  break;
689  }
690 
691  //The second pass decodes the PEM certificate
692  error = pemImportCertificate(issuerCert, issuerCertLen, derIssuerCert,
693  &derIssuerCertLen, NULL);
694  //Any error to report?
695  if(error)
696  break;
697 
698  //Parse X.509 certificate
699  error = x509ParseCertificateEx(derIssuerCert, derIssuerCertLen,
700  issuerCertInfo, &options);
701  //Any error to report?
702  if(error)
703  break;
704  }
705  else
706  {
707  //Parse X.509 certificate
708  error = x509ParseCertificateEx(issuerCert, issuerCertLen,
709  issuerCertInfo, &options);
710  //Any error to report?
711  if(error)
712  break;
713  }
714 
715  //Validate OCSP response
716  error = ocspValidateResponse(&context->ocspResponse, certInfo,
717  issuerCertInfo, context->nonce, context->nonceLen);
718  //Any error to report?
719  if(error)
720  break;
721 
722  //Update OCSP client state
723  context->state = OCSP_CLIENT_STATE_RESP_VALIDATED;
724 
725  //End of exception handling block
726  } while(0);
727 
728  //Release previously allocated memory
729  if(derCert != NULL)
730  {
731  cryptoFreeMem(derCert);
732  }
733 
734  if(derIssuerCert != NULL)
735  {
736  cryptoFreeMem(derIssuerCert);
737  }
738 
739  if(certInfo != NULL)
740  {
741  cryptoFreeMem(certInfo);
742  }
743 
744  if(issuerCertInfo != NULL)
745  {
746  cryptoFreeMem(issuerCertInfo);
747  }
748 
749  //Return status code
750  return error;
751 }
752 
753 
754 /**
755  * @brief Get OCSP response
756  * @param[in] context Pointer to the OCSP client context
757  * @return Pointer to the received OCSP response
758  **/
759 
761 {
762  const OcspResponse *response;
763 
764  //Initialize pointer
765  response = NULL;
766 
767  //Make sure the OCSP client context is valid
768  if(context != NULL)
769  {
770  //Check OCSP client state
771  if(context->state == OCSP_CLIENT_STATE_VALIDATE_RESP ||
772  context->state == OCSP_CLIENT_STATE_RESP_VALIDATED)
773  {
774  //Point to the OCSP response
775  response = &context->ocspResponse;
776  }
777  }
778 
779  //Return a pointer to the received OCSP response
780  return response;
781 }
782 
783 
784 /**
785  * @brief Get the processing status of the prior request
786  * @param[in] context Pointer to the OCSP client context
787  * @return Response status
788  **/
789 
791 {
792  OcspResponseStatus responseStatus;
793 
794  //Initialize response status
795  responseStatus = OCSP_RESP_STATUS_INTERNAL_ERROR;
796 
797  //Make sure the OCSP client context is valid
798  if(context != NULL)
799  {
800  //Check OCSP client state
801  if(context->state == OCSP_CLIENT_STATE_VALIDATE_RESP ||
802  context->state == OCSP_CLIENT_STATE_RESP_VALIDATED)
803  {
804  //The response status indicates the processing status of the request
805  responseStatus = context->ocspResponse.responseStatus;
806  }
807  }
808 
809  //Return response status
810  return responseStatus;
811 }
812 
813 
814 /**
815  * @brief Get the revocation status of the certificate
816  * @param[in] context Pointer to the OCSP client context
817  * @return Certificate status
818  **/
819 
821 {
822  OcspCertStatus certStatus;
823  OcspBasicResponse *basicResponse;
824 
825  //Initialize certificate status
826  certStatus = OCSP_CERT_STATUS_UNKNOWN;
827 
828  //Make sure the OCSP client context is valid
829  if(context != NULL)
830  {
831  //Check OCSP client state
832  if(context->state == OCSP_CLIENT_STATE_RESP_VALIDATED)
833  {
834  //Check response status
835  if(context->ocspResponse.responseStatus == OCSP_RESP_STATUS_SUCCESSFUL)
836  {
837  //Point to the TbsResponseData structure
838  basicResponse = &context->ocspResponse.basicResponse;
839  //Get the revocation status of the certificate
840  certStatus = basicResponse->tbsResponseData.responses[0].certStatus;
841  }
842  }
843  }
844 
845  //Return certificate status
846  return certStatus;
847 }
848 
849 
850 /**
851  * @brief Gracefully disconnect from the OCSP server
852  * @param[in] context Pointer to the OCSP client context
853  * @return Error code
854  **/
855 
857 {
858  error_t error;
859 
860  //Make sure the OCSP client context is valid
861  if(context == NULL)
863 
864  //Initialize status code
865  error = NO_ERROR;
866 
867  //Gracefully disconnect from the OCSP server
868  while(!error)
869  {
870  //Check OCSP client state
871  if(context->state == OCSP_CLIENT_STATE_CONNECTED)
872  {
873  //Gracefully shutdown HTTP connection
874  context->state = OCSP_CLIENT_STATE_DISCONNECTING;
875  }
876  else if(context->state == OCSP_CLIENT_STATE_DISCONNECTING)
877  {
878  //Gracefully shutdown HTTP connection
879  error = httpClientDisconnect(&context->httpClientContext);
880 
881  //Check status code
882  if(error == NO_ERROR)
883  {
884  //Close HTTP connection
885  httpClientClose(&context->httpClientContext);
886  //Update OCSP client state
887  context->state = OCSP_CLIENT_STATE_DISCONNECTED;
888  }
889  }
890  else if(context->state == OCSP_CLIENT_STATE_DISCONNECTED)
891  {
892  //The client is disconnected from the OCSP server
893  break;
894  }
895  else
896  {
897  //Invalid state
898  error = ERROR_WRONG_STATE;
899  }
900  }
901 
902  //Failed to gracefully disconnect from the OCSP server?
903  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
904  {
905  //Close HTTP connection
906  httpClientClose(&context->httpClientContext);
907  //Update OCSP client state
908  context->state = OCSP_CLIENT_STATE_DISCONNECTED;
909  }
910 
911  //Return status code
912  return error;
913 }
914 
915 
916 /**
917  * @brief Close the connection with the OCSP server
918  * @param[in] context Pointer to the OCSP client context
919  * @return Error code
920  **/
921 
923 {
924  //Make sure the OCSP client context is valid
925  if(context == NULL)
927 
928  //Close HTTP connection
929  httpClientClose(&context->httpClientContext);
930  //Update OCSP client state
931  context->state = OCSP_CLIENT_STATE_DISCONNECTED;
932 
933  //Successful processing
934  return NO_ERROR;
935 }
936 
937 
938 /**
939  * @brief Release OCSP client context
940  * @param[in] context Pointer to the OCSP client context
941  **/
942 
944 {
945  //Make sure the OCSP client context is valid
946  if(context != NULL)
947  {
948  //Release HTTP client context
949  httpClientDeinit(&context->httpClientContext);
950  //Clear OCSP client context
951  osMemset(context, 0, sizeof(OcspClientContext));
952  }
953 }
954 
955 #endif
@ OCSP_RESP_STATUS_INTERNAL_ERROR
Internal error in issuer.
Definition: ocsp_common.h:118
X.509 certificate parsing.
error_t httpClientDisconnect(HttpClientContext *context)
Gracefully disconnect from the HTTP server.
Definition: http_client.c:2202
error_t httpClientCloseBody(HttpClientContext *context)
Close HTTP request or response body.
Definition: http_client.c:2065
#define OCSP_CLIENT_MAX_URI_LEN
Definition: ocsp_client.h:76
error_t httpClientBindToInterface(HttpClientContext *context, NetInterface *interface)
Bind the HTTP client to a particular network interface.
Definition: http_client.c:297
OcspResponseStatus
OCSP response status.
Definition: ocsp_common.h:115
@ ERROR_WOULD_BLOCK
Definition: error.h:96
const OcspResponse * ocspClientGetResponse(OcspClientContext *context)
Get OCSP response.
Definition: ocsp_client.c:760
IP network address.
Definition: ip.h:90
#define PrngAlgo
Definition: crypto.h:1008
error_t httpClientReadBody(HttpClientContext *context, void *data, size_t size, size_t *received, uint_t flags)
Read HTTP response body.
Definition: http_client.c:1699
@ OCSP_CLIENT_STATE_CLOSE_BODY
Definition: ocsp_client.h:117
#define TRUE
Definition: os_port.h:50
@ OCSP_CLIENT_STATE_RECEIVE_BODY
Definition: ocsp_client.h:116
OcspResponseStatus ocspClientGetResponseStatus(OcspClientContext *context)
Get the processing status of the prior request.
Definition: ocsp_client.c:790
@ OCSP_CERT_STATUS_UNKNOWN
Definition: ocsp_common.h:133
@ OCSP_CLIENT_STATE_SEND_BODY
Definition: ocsp_client.h:113
@ OCSP_CLIENT_STATE_CONNECTING
Definition: ocsp_client.h:109
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define osStrlen(s)
Definition: os_port.h:168
OcspSingleResponse responses[OCSP_MAX_RESPONSES]
Definition: ocsp_common.h:255
@ ERROR_END_OF_STREAM
Definition: error.h:211
error_t httpClientSetVersion(HttpClientContext *context, HttpVersion version)
Set the HTTP protocol version to be used.
Definition: http_client.c:171
BasicOCSPResponse structure.
Definition: ocsp_common.h:275
OcspTbsResponseData tbsResponseData
Definition: ocsp_common.h:276
Certificate parsing options.
Definition: x509_common.h:1336
@ ERROR_WRONG_STATE
Definition: error.h:210
void httpClientDeinit(HttpClientContext *context)
Release HTTP client context.
Definition: http_client.c:2298
@ OCSP_CLIENT_STATE_DISCONNECTED
Definition: ocsp_client.h:108
error_t pemImportCertificate(const char_t *input, size_t inputLen, uint8_t *output, size_t *outputLen, size_t *consumed)
Decode a PEM file containing a certificate.
Definition: pem_import.c:55
PEM file import functions.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ERROR_UNEXPECTED_STATUS
Definition: error.h:284
error_t httpClientWriteHeader(HttpClientContext *context)
Write HTTP request header.
Definition: http_client.c:1065
const X509Options X509_DEFAULT_OPTIONS
Definition: x509_common.c:173
X.509 certificate.
Definition: x509_common.h:1121
error_t
Error codes.
Definition: error.h:43
error_t ocspClientSetPrng(OcspClientContext *context, const PrngAlgo *prngAlgo, void *prngContext)
Set the pseudo-random number generator to be used.
Definition: ocsp_client.c:128
error_t ocspClientFormatHeader(OcspClientContext *context)
Format HTTP request header.
error_t ocspClientBindToInterface(OcspClientContext *context, NetInterface *interface)
Bind the OCSP client to a particular network interface.
Definition: ocsp_client.c:222
error_t x509ParseCertificateEx(const uint8_t *data, size_t length, X509CertInfo *certInfo, const X509Options *options)
Parse a X.509 certificate.
@ OCSP_CLIENT_STATE_PARSE_HEADER
Definition: ocsp_client.h:115
error_t httpClientRegisterTlsInitCallback(HttpClientContext *context, HttpClientTlsInitCallback callback, void *param)
Register TLS initialization callback function.
Definition: http_client.c:118
error_t ocspClientInitTlsContext(HttpClientContext *httpClientContext, TlsContext *tlsContext, void *param)
TLS initialization.
OcspCertStatus
Certificate status.
Definition: ocsp_common.h:130
#define NetInterface
Definition: net.h:36
#define OCSP_CLIENT_MAX_HOST_LEN
Definition: ocsp_client.h:69
error_t httpClientSetTimeout(HttpClientContext *context, systime_t timeout)
Set communication timeout.
Definition: http_client.c:196
error_t httpClientClose(HttpClientContext *context)
Close the connection with the HTTP server.
Definition: http_client.c:2277
error_t ocspClientConnect(OcspClientContext *context, const IpAddr *serverIpAddr, uint16_t serverPort)
Specify the address of the OCSP server.
Definition: ocsp_client.c:245
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ OCSP_CLIENT_STATE_SEND_HEADER
Definition: ocsp_client.h:112
OCSP client.
error_t ocspClientSetUri(OcspClientContext *context, const char_t *uri)
Set request URI.
Definition: ocsp_client.c:198
#define OCSP_CLIENT_DEFAULT_TIMEOUT
Definition: ocsp_client.h:55
error_t ocspParseResponse(const uint8_t *data, size_t length, OcspResponse *response)
Parse OCSPResponse structure.
#define TRACE_INFO(...)
Definition: debug.h:105
#define OCSP_CLIENT_BUFFER_SIZE
Definition: ocsp_client.h:62
OCSP response parsing.
error_t httpClientInit(HttpClientContext *context)
Initialize HTTP client context.
Definition: http_client.c:66
error_t ocspClientRegisterTlsInitCallback(OcspClientContext *context, OcspClientTlsInitCallback callback)
Register TLS initialization callback function.
Definition: ocsp_client.c:103
error_t httpClientReadHeader(HttpClientContext *context)
Read HTTP response header.
Definition: http_client.c:1425
error_t ocspClientSetTimeout(OcspClientContext *context, systime_t timeout)
Set communication timeout.
Definition: ocsp_client.c:152
uint32_t systime_t
System time.
char char_t
Definition: compiler_port.h:55
error_t ocspClientGenerateNonce(OcspClientContext *context)
Nonce generation.
error_t httpClientConnect(HttpClientContext *context, const IpAddr *serverIpAddr, uint16_t serverPort)
Establish a connection with the specified HTTP server.
Definition: http_client.c:320
@ OCSP_CLIENT_STATE_VALIDATE_RESP
Definition: ocsp_client.h:119
OcspCertStatus certStatus
Definition: ocsp_common.h:225
error_t ocspValidateResponse(const OcspResponse *response, const X509CertInfo *certInfo, const X509CertInfo *issuerCertInfo, const uint8_t *nonce, size_t nonceLen)
OCSP response validation.
uint8_t n
@ OCSP_CLIENT_STATE_RESP_VALIDATED
Definition: ocsp_client.h:120
@ HTTP_VERSION_1_1
Definition: http_common.h:63
error_t ocspClientParseHeader(OcspClientContext *context)
Parse HTTP response header.
OcspCertStatus ocspClientGetCertificateStatus(OcspClientContext *context)
Get the revocation status of the certificate.
Definition: ocsp_client.c:820
error_t httpClientWriteBody(HttpClientContext *context, const void *data, size_t length, size_t *written, uint_t flags)
Write HTTP request body.
Definition: http_client.c:1188
@ OCSP_CLIENT_STATE_DISCONNECTING
Definition: ocsp_client.h:121
#define cryptoFreeMem(p)
Definition: crypto.h:861
OCSP response validation.
error_t ocspClientInit(OcspClientContext *context)
OCSP client initialization.
Definition: ocsp_client.c:61
@ OCSP_CLIENT_STATE_CONNECTED
Definition: ocsp_client.h:110
#define cryptoAllocMem(size)
Definition: crypto.h:856
uint8_t options[]
Definition: tcp.h:364
Helper functions for OCSP client.
error_t(* OcspClientTlsInitCallback)(OcspClientContext *context, TlsContext *tlsContext)
TLS initialization callback function.
Definition: ocsp_client.h:132
error_t ocspClientCreateRequest(OcspClientContext *context, const char_t *cert, size_t certLen, const char_t *issuerCert, size_t issuerCertLen)
Create OCSP request.
Definition: ocsp_client.c:357
error_t ocspClientFormatRequest(OcspClientContext *context, const char_t *cert, size_t certLen, const char_t *issuerCert, size_t issuerCertLen)
Format OCSP request.
error_t ocspClientClose(OcspClientContext *context)
Close the connection with the OCSP server.
Definition: ocsp_client.c:922
#define OcspClientContext
Definition: ocsp_client.h:95
error_t ocspClientSetHost(OcspClientContext *context, const char_t *host)
Set the domain name of the OCSP server.
Definition: ocsp_client.c:173
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t ocspClientValidateResponse(OcspClientContext *context, const char_t *cert, size_t certLen, const char_t *issuerCert, size_t issuerCertLen)
Validate OCSP response.
Definition: ocsp_client.c:581
error_t ocspClientDisconnect(OcspClientContext *context)
Gracefully disconnect from the OCSP server.
Definition: ocsp_client.c:856
@ OCSP_RESP_STATUS_SUCCESSFUL
Response has valid confirmations.
Definition: ocsp_common.h:116
error_t ocspClientSendRequest(OcspClientContext *context)
Perform OCSP request/response transaction.
Definition: ocsp_client.c:404
@ OCSP_CLIENT_STATE_FORMAT_HEADER
Definition: ocsp_client.h:111
#define osStrcpy(s1, s2)
Definition: os_port.h:210
OCSPResponse structure.
Definition: ocsp_common.h:288
@ OCSP_CLIENT_STATE_RECEIVE_HEADER
Definition: ocsp_client.h:114
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ OCSP_CLIENT_STATE_PARSE_RESP
Definition: ocsp_client.h:118
void ocspClientDeinit(OcspClientContext *context)
Release OCSP client context.
Definition: ocsp_client.c:943