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-2024 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.4.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
83 
84  //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  //Register TLS initialization callback
269  context->tlsInitCallback);
270 #endif
271  //Check status code
272  if(!error)
273  {
274  //Select HTTP protocol version
275  error = httpClientSetVersion(&context->httpClientContext,
277  }
278 
279  //Check status code
280  if(!error)
281  {
282  //Set timeout value for blocking operations
283  error = httpClientSetTimeout(&context->httpClientContext,
284  context->timeout);
285  }
286 
287  //Check status code
288  if(!error)
289  {
290  //Bind the HTTP client to the relevant network interface
292  context->interface);
293  }
294 
295  //Check status code
296  if(!error)
297  {
298  //Establish HTTP connection
300  }
301  }
302  else if(context->state == OCSP_CLIENT_STATE_CONNECTING)
303  {
304  //Establish HTTP connection
305  error = httpClientConnect(&context->httpClientContext, serverIpAddr,
306  serverPort);
307 
308  //Check status code
309  if(error == NO_ERROR)
310  {
311  //The HTTP connection is established
313  }
314  }
315  else if(context->state == OCSP_CLIENT_STATE_CONNECTED)
316  {
317  //The client is connected to the OCSP server
318  break;
319  }
320  else
321  {
322  //Invalid state
323  error = ERROR_WRONG_STATE;
324  }
325  }
326 
327  //Failed to establish connection with the OCSP server?
328  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
329  {
330  //Clean up side effects
332  //Update OCSP client state
334  }
335 
336  //Return status code
337  return error;
338 }
339 
340 
341 /**
342  * @brief Create OCSP request
343  * @param[in] context Pointer to the OCSP client context
344  * @param[in] cert Certificate to be checked (PEM or DER format)
345  * @param[in] certLen Length of the certificate, in bytes
346  * @param[in] issuerCert Issuer's certificate (PEM or DER format)
347  * @param[in] issuerCertLen Length of the issuer certificate, in bytes
348  * @return Error code
349  **/
350 
352  const char_t *cert, size_t certLen, const char_t *issuerCert,
353  size_t issuerCertLen)
354 {
355  error_t error;
356 
357  //Check parameters
358  if(context == NULL || cert == NULL || issuerCert == NULL)
360 
361  //Check OCSP client state
362  if(context->state != OCSP_CLIENT_STATE_CONNECTED &&
363  context->state != OCSP_CLIENT_STATE_PARSE_RESP &&
366  {
367  return ERROR_WRONG_STATE;
368  }
369 
370  //The value of the nonce must be generated using a cryptographically strong
371  //pseudorandom number generator
372  error = ocspClientGenerateNonce(context);
373  //Any error to report?
374  if(error)
375  return error;
376 
377  //Format OCSP request
378  error = ocspClientFormatRequest(context, cert, certLen, issuerCert,
379  issuerCertLen);
380  //Any error to report?
381  if(error)
382  return error;
383 
384  //Update OCSP client state
386 
387  //Successful processing
388  return NO_ERROR;
389 }
390 
391 
392 /**
393  * @brief Perform OCSP request/response transaction
394  * @param[in] context Pointer to the OCSP client context
395  * @return Error code
396  **/
397 
399 {
400  error_t error;
401  size_t n;
402 
403  //Make sure the OCSP client context is valid
404  if(context == NULL)
406 
407  //Initialize status code
408  error = NO_ERROR;
409 
410  //Perform HTTP request
411  while(!error)
412  {
413  //Check OCSP client state
414  if(context->state == OCSP_CLIENT_STATE_FORMAT_HEADER)
415  {
416  //Format HTTP request header
417  error = ocspClientFormatHeader(context);
418 
419  //Check status code
420  if(!error)
421  {
422  //Update OCSP client state
424  }
425  }
426  else if(context->state == OCSP_CLIENT_STATE_SEND_HEADER)
427  {
428  //Send HTTP request header
429  error = httpClientWriteHeader(&context->httpClientContext);
430 
431  //Check status code
432  if(!error)
433  {
434  //Point to the first byte of the body
435  context->bufferPos = 0;
436 
437  //Update OCSP client state
439  }
440  }
441  else if(context->state == OCSP_CLIENT_STATE_SEND_BODY)
442  {
443  //Send HTTP request body
444  if(context->bufferPos < context->bufferLen)
445  {
446  //Send more data
447  error = httpClientWriteBody(&context->httpClientContext,
448  context->buffer + context->bufferPos,
449  context->bufferLen - context->bufferPos, &n, 0);
450 
451  //Check status code
452  if(!error)
453  {
454  //Advance data pointer
455  context->bufferPos += n;
456  }
457  }
458  else
459  {
460  //Update HTTP request state
462  }
463  }
464  else if(context->state == OCSP_CLIENT_STATE_RECEIVE_HEADER)
465  {
466  //Receive HTTP response header
467  error = httpClientReadHeader(&context->httpClientContext);
468 
469  //Check status code
470  if(!error)
471  {
472  //Update OCSP client state
474  }
475  }
476  else if(context->state == OCSP_CLIENT_STATE_PARSE_HEADER)
477  {
478  //Parse HTTP response header
479  error = ocspClientParseHeader(context);
480 
481  //Check status code
482  if(!error)
483  {
484  //Flush the receive buffer
485  context->bufferLen = 0;
486  context->bufferPos = 0;
487 
488  //Update OCSP client state
490  }
491  }
492  else if(context->state == OCSP_CLIENT_STATE_RECEIVE_BODY)
493  {
494  //Receive HTTP response body
495  if(context->bufferLen < OCSP_CLIENT_BUFFER_SIZE)
496  {
497  //Receive more data
498  error = httpClientReadBody(&context->httpClientContext,
499  context->buffer + context->bufferLen,
500  OCSP_CLIENT_BUFFER_SIZE - context->bufferLen, &n, 0);
501 
502  //Check status code
503  if(error == NO_ERROR)
504  {
505  //Advance data pointer
506  context->bufferLen += n;
507  }
508  else if(error == ERROR_END_OF_STREAM)
509  {
510  //The end of the response body has been reached
511  error = NO_ERROR;
512 
513  //Update OCSP client state
515  }
516  else
517  {
518  //Just for sanity
519  }
520  }
521  else
522  {
523  //Update OCSP client state
525  }
526  }
527  else if(context->state == OCSP_CLIENT_STATE_CLOSE_BODY)
528  {
529  //Close HTTP response body
530  error = httpClientCloseBody(&context->httpClientContext);
531 
532  //Check status code
533  if(!error)
534  {
535  //Update OCSP client state
537  }
538  }
539  else if(context->state == OCSP_CLIENT_STATE_PARSE_RESP)
540  {
541  //Parse OCSP response
542  error = ocspParseResponse(context->buffer, context->bufferLen,
543  &context->ocspResponse);
544 
545  //Check status code
546  if(!error)
547  {
548  //Update OCSP client state
550  break;
551  }
552  }
553  else
554  {
555  //Invalid state
556  error = ERROR_WRONG_STATE;
557  }
558  }
559 
560  //Return status code
561  return error;
562 }
563 
564 
565 /**
566  * @brief Validate OCSP response
567  * @param[in] context Pointer to the OCSP client context
568  * @param[in] cert Certificate to be checked (PEM or DER format)
569  * @param[in] certLen Length of the certificate, in bytes
570  * @param[in] issuerCert Issuer's certificate (PEM or DER format)
571  * @param[in] issuerCertLen Length of the issuer certificate, in bytes
572  * @return Error code
573  **/
574 
576  const char_t *cert, size_t certLen, const char_t *issuerCert,
577  size_t issuerCertLen)
578 {
579  error_t error;
580  uint8_t *derCert;
581  size_t derCertLen;
582  uint8_t *derIssuerCert;
583  size_t derIssuerCertLen;
584  X509CertInfo *certInfo;
585  X509CertInfo *issuerCertInfo;
586 
587  //Check parameters
588  if(context == NULL || cert == NULL || issuerCert == NULL)
590 
591  //Check OCSP client state
592  if(context->state != OCSP_CLIENT_STATE_VALIDATE_RESP)
593  return ERROR_WRONG_STATE;
594 
595  //Check response status
598 
599  //Initialize variables
600  derCert = NULL;
601  derIssuerCert = NULL;
602  certInfo = NULL;
603  issuerCertInfo = NULL;
604 
605  //Start of exception handling block
606  do
607  {
608  //Allocate a memory buffer to store X.509 certificate info
609  certInfo = cryptoAllocMem(sizeof(X509CertInfo));
610  //Failed to allocate memory?
611  if(certInfo == NULL)
612  {
613  error = ERROR_OUT_OF_MEMORY;
614  break;
615  }
616 
617  //The OCSP client accepts certificates in either PEM or DER format
618  error = pemImportCertificate(cert, certLen, NULL, &derCertLen, NULL);
619 
620  //PEM or DER format?
621  if(!error)
622  {
623  //Allocate a memory buffer to hold the DER-encoded certificate
624  derCert = cryptoAllocMem(derCertLen);
625  //Failed to allocate memory?
626  if(derCert == NULL)
627  {
628  error = ERROR_OUT_OF_MEMORY;
629  break;
630  }
631 
632  //The second pass decodes the PEM certificate
633  error = pemImportCertificate(cert, certLen, derCert, &derCertLen, NULL);
634  //Any error to report?
635  if(error)
636  break;
637 
638  //Parse X.509 certificate
639  error = x509ParseCertificateEx(derCert, derCertLen, certInfo, TRUE);
640  //Any error to report?
641  if(error)
642  break;
643  }
644  else
645  {
646  //Parse X.509 certificate
647  error = x509ParseCertificateEx(cert, certLen, certInfo, TRUE);
648  //Any error to report?
649  if(error)
650  break;
651  }
652 
653  //Allocate a memory buffer to store X.509 certificate info
654  issuerCertInfo = cryptoAllocMem(sizeof(X509CertInfo));
655  //Failed to allocate memory?
656  if(certInfo == NULL)
657  {
658  error = ERROR_OUT_OF_MEMORY;
659  break;
660  }
661 
662  //The OCSP client accepts certificates in either PEM or DER format
663  error = pemImportCertificate(issuerCert, issuerCertLen, NULL,
664  &derIssuerCertLen, NULL);
665 
666  //PEM or DER format?
667  if(!error)
668  {
669  //Allocate a memory buffer to hold the DER-encoded certificate
670  derIssuerCert = cryptoAllocMem(derIssuerCertLen);
671  //Failed to allocate memory?
672  if(derCert == NULL)
673  {
674  error = ERROR_OUT_OF_MEMORY;
675  break;
676  }
677 
678  //The second pass decodes the PEM certificate
679  error = pemImportCertificate(issuerCert, issuerCertLen, derIssuerCert,
680  &derIssuerCertLen, NULL);
681  //Any error to report?
682  if(error)
683  break;
684 
685  //Parse X.509 certificate
686  error = x509ParseCertificateEx(derIssuerCert, derIssuerCertLen,
687  issuerCertInfo, TRUE);
688  //Any error to report?
689  if(error)
690  break;
691  }
692  else
693  {
694  //Parse X.509 certificate
695  error = x509ParseCertificateEx(issuerCert, issuerCertLen,
696  issuerCertInfo, TRUE);
697  //Any error to report?
698  if(error)
699  break;
700  }
701 
702  //Validate OCSP response
703  error = ocspValidateResponse(&context->ocspResponse, certInfo,
704  issuerCertInfo, context->nonce, context->nonceLen);
705  //Any error to report?
706  if(error)
707  break;
708 
709  //Update OCSP client state
711 
712  //End of exception handling block
713  } while(0);
714 
715  //Release previously allocated memory
716  if(derCert != NULL)
717  {
718  cryptoFreeMem(derCert);
719  }
720 
721  if(derIssuerCert != NULL)
722  {
723  cryptoFreeMem(derIssuerCert);
724  }
725 
726  if(certInfo != NULL)
727  {
728  cryptoFreeMem(certInfo);
729  }
730 
731  if(issuerCertInfo != NULL)
732  {
733  cryptoFreeMem(issuerCertInfo);
734  }
735 
736  //Return status code
737  return error;
738 }
739 
740 
741 /**
742  * @brief Get OCSP response
743  * @param[in] context Pointer to the OCSP client context
744  * @return Pointer to the received OCSP response
745  **/
746 
748 {
749  const OcspResponse *response;
750 
751  //Initialize pointer
752  response = NULL;
753 
754  //Make sure the OCSP client context is valid
755  if(context != NULL)
756  {
757  //Check OCSP client state
758  if(context->state == OCSP_CLIENT_STATE_VALIDATE_RESP ||
760  {
761  //Point to the OCSP response
762  response = &context->ocspResponse;
763  }
764  }
765 
766  //Return a pointer to the received OCSP response
767  return response;
768 }
769 
770 
771 /**
772  * @brief Get the processing status of the prior request
773  * @param[in] context Pointer to the OCSP client context
774  * @return Response status
775  **/
776 
778 {
779  OcspResponseStatus responseStatus;
780 
781  //Initialize response status
782  responseStatus = OCSP_RESP_STATUS_INTERNAL_ERROR;
783 
784  //Make sure the OCSP client context is valid
785  if(context != NULL)
786  {
787  //Check OCSP client state
788  if(context->state == OCSP_CLIENT_STATE_VALIDATE_RESP ||
790  {
791  //The response status indicates the processing status of the request
792  responseStatus = context->ocspResponse.responseStatus;
793  }
794  }
795 
796  //Return response status
797  return responseStatus;
798 }
799 
800 
801 /**
802  * @brief Get the revocation status of the certificate
803  * @param[in] context Pointer to the OCSP client context
804  * @return Certificate status
805  **/
806 
808 {
809  OcspCertStatus certStatus;
810  OcspBasicResponse *basicResponse;
811 
812  //Initialize certificate status
813  certStatus = OCSP_CERT_STATUS_UNKNOWN;
814 
815  //Make sure the OCSP client context is valid
816  if(context != NULL)
817  {
818  //Check OCSP client state
820  {
821  //Check response status
823  {
824  //Point to the TbsResponseData structure
825  basicResponse = &context->ocspResponse.basicResponse;
826  //Get the revocation status of the certificate
827  certStatus = basicResponse->tbsResponseData.responses[0].certStatus;
828  }
829  }
830  }
831 
832  //Return certificate status
833  return certStatus;
834 }
835 
836 
837 /**
838  * @brief Gracefully disconnect from the OCSP server
839  * @param[in] context Pointer to the OCSP client context
840  * @return Error code
841  **/
842 
844 {
845  error_t error;
846 
847  //Make sure the OCSP client context is valid
848  if(context == NULL)
850 
851  //Initialize status code
852  error = NO_ERROR;
853 
854  //Gracefully disconnect from the OCSP server
855  while(!error)
856  {
857  //Check OCSP client state
858  if(context->state == OCSP_CLIENT_STATE_CONNECTED)
859  {
860  //Gracefully shutdown HTTP connection
862  }
863  else if(context->state == OCSP_CLIENT_STATE_DISCONNECTING)
864  {
865  //Gracefully shutdown HTTP connection
866  error = httpClientDisconnect(&context->httpClientContext);
867 
868  //Check status code
869  if(error == NO_ERROR)
870  {
871  //Close HTTP connection
873  //Update OCSP client state
875  }
876  }
877  else if(context->state == OCSP_CLIENT_STATE_DISCONNECTED)
878  {
879  //The client is disconnected from the OCSP server
880  break;
881  }
882  else
883  {
884  //Invalid state
885  error = ERROR_WRONG_STATE;
886  }
887  }
888 
889  //Failed to gracefully disconnect from the OCSP server?
890  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
891  {
892  //Close HTTP connection
894  //Update OCSP client state
896  }
897 
898  //Return status code
899  return error;
900 }
901 
902 
903 /**
904  * @brief Close the connection with the OCSP server
905  * @param[in] context Pointer to the OCSP client context
906  * @return Error code
907  **/
908 
910 {
911  //Make sure the OCSP client context is valid
912  if(context == NULL)
914 
915  //Close HTTP connection
917  //Update OCSP client state
919 
920  //Successful processing
921  return NO_ERROR;
922 }
923 
924 
925 /**
926  * @brief Release OCSP client context
927  * @param[in] context Pointer to the OCSP client context
928  **/
929 
931 {
932  //Make sure the OCSP client context is valid
933  if(context != NULL)
934  {
935  //Release HTTP client context
937  //Clear OCSP client context
938  osMemset(context, 0, sizeof(OcspClientContext));
939  }
940 }
941 
942 #endif
@ OCSP_RESP_STATUS_INTERNAL_ERROR
Internal error in issuer.
Definition: ocsp_common.h:118
X.509 certificate parsing.
NetInterface * interface
Underlying network interface.
Definition: ocsp_client.h:141
error_t httpClientDisconnect(HttpClientContext *context)
Gracefully disconnect from the HTTP server.
Definition: http_client.c:2149
error_t httpClientCloseBody(HttpClientContext *context)
Close HTTP request or response body.
Definition: http_client.c:2012
#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:246
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:747
IP network address.
Definition: ip.h:90
#define PrngAlgo
Definition: crypto.h:938
size_t bufferLen
Length of the buffer, in bytes.
Definition: ocsp_client.h:155
error_t httpClientReadBody(HttpClientContext *context, void *data, size_t size, size_t *received, uint_t flags)
Read HTTP response body.
Definition: http_client.c:1646
uint8_t nonce[OCSP_CLIENT_NONCE_SIZE]
Random nonce.
Definition: ocsp_client.h:152
@ OCSP_CLIENT_STATE_CLOSE_BODY
Definition: ocsp_client.h:113
#define TRUE
Definition: os_port.h:50
uint8_t buffer[OCSP_CLIENT_BUFFER_SIZE]
Memory buffer for input/output operations.
Definition: ocsp_client.h:154
@ OCSP_CLIENT_STATE_RECEIVE_BODY
Definition: ocsp_client.h:112
OcspResponseStatus ocspClientGetResponseStatus(OcspClientContext *context)
Get the processing status of the prior request.
Definition: ocsp_client.c:777
@ OCSP_CERT_STATUS_UNKNOWN
Definition: ocsp_common.h:133
@ OCSP_CLIENT_STATE_SEND_BODY
Definition: ocsp_client.h:109
@ OCSP_CLIENT_STATE_CONNECTING
Definition: ocsp_client.h:105
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
char_t serverName[OCSP_CLIENT_MAX_HOST_LEN+1]
Host name of the OCSP server.
Definition: ocsp_client.h:149
#define osStrlen(s)
Definition: os_port.h:165
OcspClientState state
OCSP client state.
Definition: ocsp_client.h:140
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ocsp_client.h:143
OcspSingleResponse responses[OCSP_MAX_RESPONSES]
Definition: ocsp_common.h:255
@ ERROR_END_OF_STREAM
Definition: error.h:210
error_t httpClientSetVersion(HttpClientContext *context, HttpVersion version)
Set the HTTP protocol version to be used.
Definition: http_client.c:162
BasicOCSPResponse structure.
Definition: ocsp_common.h:275
OCSP client context.
Definition: ocsp_client.h:139
error_t(* OcspClientTlsInitCallback)(HttpClientContext *context, TlsContext *tlsContext)
TLS initialization callback function.
Definition: ocsp_client.h:128
OcspTbsResponseData tbsResponseData
Definition: ocsp_common.h:276
@ ERROR_WRONG_STATE
Definition: error.h:209
void httpClientDeinit(HttpClientContext *context)
Release HTTP client context.
Definition: http_client.c:2245
@ OCSP_CLIENT_STATE_DISCONNECTED
Definition: ocsp_client.h:104
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:61
PEM file import functions.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
size_t nonceLen
Length of the nonce, in bytes.
Definition: ocsp_client.h:153
@ ERROR_UNEXPECTED_STATUS
Definition: error.h:283
error_t httpClientWriteHeader(HttpClientContext *context)
Write HTTP request header.
Definition: http_client.c:1014
X.509 certificate.
Definition: x509_common.h:1071
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
@ OCSP_CLIENT_STATE_PARSE_HEADER
Definition: ocsp_client.h:111
OcspCertStatus
Certificate status.
Definition: ocsp_common.h:130
OcspBasicResponse basicResponse
Definition: ocsp_common.h:292
error_t httpClientRegisterTlsInitCallback(HttpClientContext *context, HttpClientTlsInitCallback callback)
Register TLS initialization callback function.
Definition: http_client.c:111
#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:187
error_t httpClientClose(HttpClientContext *context)
Close the connection with the HTTP server.
Definition: http_client.c:2224
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:108
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:95
#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
OcspClientTlsInitCallback tlsInitCallback
TLS initialization callback function.
Definition: ocsp_client.h:147
error_t httpClientReadHeader(HttpClientContext *context)
Read HTTP response header.
Definition: http_client.c:1372
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:48
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:269
@ OCSP_CLIENT_STATE_VALIDATE_RESP
Definition: ocsp_client.h:115
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:116
@ 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:807
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:1137
@ OCSP_CLIENT_STATE_DISCONNECTING
Definition: ocsp_client.h:117
systime_t timeout
Timeout value.
Definition: ocsp_client.h:142
#define cryptoFreeMem(p)
Definition: crypto.h:791
OCSP response validation.
error_t ocspClientInit(OcspClientContext *context)
OCSP client initialization.
Definition: ocsp_client.c:61
error_t x509ParseCertificateEx(const uint8_t *data, size_t length, X509CertInfo *certInfo, bool_t ignoreUnknown)
Parse a X.509 certificate.
@ OCSP_CLIENT_STATE_CONNECTED
Definition: ocsp_client.h:106
#define cryptoAllocMem(size)
Definition: crypto.h:786
Helper functions for OCSP client.
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:351
void * prngContext
Pseudo-random number generator context.
Definition: ocsp_client.h:144
error_t ocspClientFormatRequest(OcspClientContext *context, const char_t *cert, size_t certLen, const char_t *issuerCert, size_t issuerCertLen)
Format OCSP request.
OcspResponse ocspResponse
OCSP response.
Definition: ocsp_client.h:158
size_t bufferPos
Current position in the buffer.
Definition: ocsp_client.h:156
error_t ocspClientClose(OcspClientContext *context)
Close the connection with the OCSP server.
Definition: ocsp_client.c:909
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:135
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:575
error_t ocspClientDisconnect(OcspClientContext *context)
Gracefully disconnect from the OCSP server.
Definition: ocsp_client.c:843
@ 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:398
@ OCSP_CLIENT_STATE_FORMAT_HEADER
Definition: ocsp_client.h:107
#define osStrcpy(s1, s2)
Definition: os_port.h:207
OcspResponseStatus responseStatus
Definition: ocsp_common.h:290
OCSPResponse structure.
Definition: ocsp_common.h:288
@ OCSP_CLIENT_STATE_RECEIVE_HEADER
Definition: ocsp_client.h:110
HttpClientContext httpClientContext
HTTP client context.
Definition: ocsp_client.h:145
uint16_t serverPort
TCP port number.
Definition: ocsp_client.h:150
char_t uri[OCSP_CLIENT_MAX_URI_LEN+1]
URI.
Definition: ocsp_client.h:151
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ OCSP_CLIENT_STATE_PARSE_RESP
Definition: ocsp_client.h:114
void ocspClientDeinit(OcspClientContext *context)
Release OCSP client context.
Definition: ocsp_client.c:930