ocsp_resp_parse.c
Go to the documentation of this file.
1 /**
2  * @file ocsp_resp_parse.c
3  * @brief OCSP response parsing
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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL OCSP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ocsp/ocsp_resp_parse.h"
36 #include "encoding/asn1.h"
37 #include "encoding/oid.h"
38 #include "pkix/x509_cert_parse.h"
40 #include "pkix/x509_sign_parse.h"
41 #include "debug.h"
42 
43 //Check crypto library configuration
44 #if (OCSP_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Parse OCSPResponse structure
49  * @param[in] data Pointer to the X.509 certificate to parse
50  * @param[in] length Length of the X.509 certificate
51  * @param[out] response Information resulting from the parsing process
52  * @return Error code
53  **/
54 
55 error_t ocspParseResponse(const uint8_t *data, size_t length,
56  OcspResponse *response)
57 {
58  error_t error;
59  size_t n;
60  Asn1Tag tag;
61 
62  //Check parameters
63  if(data == NULL || response == NULL)
65 
66  //Debug message
67  TRACE_DEBUG("OCSP response (%" PRIuSIZE " bytes):\r\n", length);
68  //Dump OCSP response
70 
71  //Clear the OCSP response structure
72  osMemset(response, 0, sizeof(OcspResponse));
73 
74  //Raw contents of the OCSPResponse structure
75  response->raw.value = data;
76  response->raw.length = length;
77 
78  //The OCSPResponse structure is encapsulated within a sequence
79  error = asn1ReadSequence(data, length, &tag);
80  //Failed to decode ASN.1 tag?
81  if(error)
82  return error;
83 
84  //Point to the first field of the sequence
85  data = tag.value;
86  length = tag.length;
87 
88  //An OCSP response at a minimum consists of a ResponseStatus field
89  //indicating the processing status of the prior request (refer to
90  //RFC 6960, section 4.2.1)
92  &response->responseStatus);
93  //Any error to report?
94  if(error)
95  return error;
96 
97  //Point to the next field
98  data += n;
99  length -= n;
100 
101  //Check response status
103  {
104  //An OCSP response consists of a response type and the bytes of the
105  //actual response
106  error = ocspParseResponseBytes(data, length, response);
107  }
108  else
109  {
110  //If the value of ResponseStatus is one of the error conditions, the
111  //ResponseBytes field is not set
112  }
113 
114  //Return status code
115  return error;
116 }
117 
118 
119 /**
120  * @brief Parse ResponseStatus field
121  * @param[in] data Pointer to the ASN.1 structure to parse
122  * @param[in] length Length of the ASN.1 structure
123  * @param[out] totalLength Number of bytes that have been parsed
124  * @param[out] status OCSP response status
125  * @return Error code
126  **/
127 
129  size_t *totalLength, OcspResponseStatus *status)
130 {
131  error_t error;
132  Asn1Tag tag;
133 
134  //Read ASN.1 tag
135  error = asn1ReadTag(data, length, &tag);
136  //Failed to decode ASN.1 tag?
137  if(error)
138  return error;
139 
140  //Enforce encoding, class and type
141  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
143  //Invalid tag?
144  if(error)
145  return error;
146 
147  //Check the length of the field
148  if(tag.length != 1)
149  return ERROR_INVALID_SYNTAX;
150 
151  //Save the total length of the field
152  *totalLength = tag.totalLength;
153 
154  //The response status indicates the processing status of the request
155  *status = (OcspResponseStatus) tag.value[0];
156 
157  //Successful processing
158  return NO_ERROR;
159 }
160 
161 
162 /**
163  * @brief Parse ResponseBytes structure
164  * @param[in] data Pointer to the ASN.1 structure to parse
165  * @param[in] length Length of the ASN.1 structure
166  * @param[out] response Information resulting from the parsing process
167  * @return Error code
168  **/
169 
170 error_t ocspParseResponseBytes(const uint8_t *data, size_t length,
171  OcspResponse *response)
172 {
173  error_t error;
174  Asn1Tag tag;
175 
176  //Explicit tagging shall be used to encode the ResponseBytes structure
177  error = asn1ReadTag(data, length, &tag);
178  //Failed to decode ASN.1 tag?
179  if(error)
180  return error;
181 
182  //Enforce encoding, class and type
183  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
184  //Invalid tag?
185  if(error)
186  return error;
187 
188  //Read the inner sequence
189  error = asn1ReadSequence(tag.value, tag.length, &tag);
190  //Failed to decode ASN.1 tag?
191  if(error)
192  return error;
193 
194  //Point to the first field of the sequence
195  data = tag.value;
196  length = tag.length;
197 
198  //Read ResponseType field
199  error = asn1ReadOid(data, length, &tag);
200  //Failed to decode ASN.1 tag?
201  if(error)
202  return error;
203 
204  //Save the OID
205  response->responseType.value = tag.value;
206  response->responseType.length = tag.length;
207 
208  //Point to the next field
209  data += tag.totalLength;
210  length -= tag.totalLength;
211 
212  //Read Response field
213  error = asn1ReadOctetString(data, length, &tag);
214  //Failed to decode ASN.1 tag?
215  if(error)
216  return error;
217 
218  //Point to the first byte of the actual response
219  data = tag.value;
220  length = tag.length;
221 
222  //OCSP clients shall be capable of receiving and processing responses of
223  //the id-pkix-ocsp-basic response type (refer to RFC 6960, section 4.2.1)
224  if(!oidComp(response->responseType.value, response->responseType.length,
226  {
227  //The value for response shall be the DER encoding of BasicOCSPResponse
229  &response->basicResponse);
230  }
231  else
232  {
233  //Unknown response type
234  error = ERROR_WRONG_IDENTIFIER;
235  }
236 
237  //Return status code
238  return error;
239 }
240 
241 
242 /**
243  * @brief Parse BasicOCSPResponse structure
244  * @param[in] data Pointer to the ASN.1 structure to parse
245  * @param[in] length Length of the ASN.1 structure
246  * @param[out] basicResponse Information resulting from the parsing process
247  * @return Error code
248  **/
249 
250 error_t ocspParseBasicResponse(const uint8_t *data, size_t length,
251  OcspBasicResponse *basicResponse)
252 {
253  error_t error;
254  size_t n;
255  Asn1Tag tag;
256 
257  //Debug message
258  TRACE_DEBUG("OCSP basic response (%" PRIuSIZE " bytes):\r\n", length);
259  //Dump OCSP response
261 
262  //The BasicOCSPResponse structure is encapsulated within a sequence
263  error = asn1ReadSequence(data, length, &tag);
264  //Failed to decode ASN.1 tag?
265  if(error)
266  return error;
267 
268  //Point to the first field of the sequence
269  data = tag.value;
270  length = tag.length;
271 
272  //Parse TbsResponseData structure
274  &basicResponse->tbsResponseData);
275  //Any error to report?
276  if(error)
277  return error;
278 
279  //Point to the next field
280  data += n;
281  length -= n;
282 
283  //Parse SignatureAlgorithm structure
284  error = x509ParseSignatureAlgo(data, length, &n,
285  &basicResponse->signatureAlgo);
286  //Any error to report?
287  if(error)
288  return error;
289 
290  //Point to the next field
291  data += n;
292  length -= n;
293 
294  //Parse Signature structure
296  &basicResponse->signature);
297  //Any error to report?
298  if(error)
299  return error;
300 
301  //Point to the next field
302  data += n;
303  length -= n;
304 
305  //The responder may include certificates in the Certs field of
306  //BasicOCSPResponse that help the OCSP client verify the responder's
307  //signature (refer to RFC 6960, section 4.2.1)
308  if(length > 0)
309  {
310  //Parse ASN.1 tag
311  error = asn1ReadTag(data, length, &tag);
312  //Failed to decode ASN.1 tag?
313  if(error)
314  return error;
315 
316  //Enforce encoding, class and type
317  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
318 
319  //Check whether the Certs field is present
320  if(!error)
321  {
322  //Parse Certs field
323  error = ocspParseCerts(tag.value, tag.length, &basicResponse->certs);
324  //Any error to report?
325  if(error)
326  return error;
327  }
328  }
329  else
330  {
331  //If no certificates are included, then Certs should be absent
332  }
333 
334  //Certificate successfully parsed
335  return NO_ERROR;
336 }
337 
338 
339 /**
340  * @brief Parse TbsResponseData structure
341  * @param[in] data Pointer to the ASN.1 structure to parse
342  * @param[in] length Length of the ASN.1 structure
343  * @param[out] totalLength Number of bytes that have been parsed
344  * @param[out] tbsResponseData Information resulting from the parsing process
345  * @return Error code
346  **/
347 
349  size_t *totalLength, OcspTbsResponseData *tbsResponseData)
350 {
351  error_t error;
352  size_t n;
353  Asn1Tag tag;
354 
355  //The TbsResponseData structure is encapsulated within a sequence
356  error = asn1ReadSequence(data, length, &tag);
357  //Failed to decode ASN.1 tag?
358  if(error)
359  return error;
360 
361  //Save the total length of the field
362  *totalLength = tag.totalLength;
363 
364  //The ASN.1 DER-encoded TbsResponseData is used as the input to the
365  //signature function
366  tbsResponseData->raw.value = data;
367  tbsResponseData->raw.length = tag.totalLength;
368 
369  //Point to the first field of the sequence
370  data = tag.value;
371  length = tag.length;
372 
373  //The Version field contains the version of the response syntax
374  error = ocspParseVersion(data, length, &n, &tbsResponseData->version);
375  //Any error to report?
376  if(error)
377  return error;
378 
379  //The version must be v1 for this version of the basic response syntax (refer
380  //to RFC 6960, section 4.2.2.3)
381  if(tbsResponseData->version != OCSP_VERSION_1)
382  return ERROR_INVALID_VERSION;
383 
384  //Point to the next field
385  data += n;
386  length -= n;
387 
388  //The ResponderID field contains either the name of the responder or a hash
389  //of the responder's public key
390  error = ocspParseResponderId(data, length, &n,
391  &tbsResponseData->responderId);
392  //Any error to report?
393  if(error)
394  return error;
395 
396  //Point to the next field
397  data += n;
398  length -= n;
399 
400  //The ProducedAt field indicated the time at which the response was generated
401  error = x509ParseTime(data, length, &n, &tbsResponseData->producedAt);
402  //Any error to report?
403  if(error)
404  return error;
405 
406  //Point to the next field
407  data += n;
408  length -= n;
409 
410  //The basic response contains responses for each of the certificates in a
411  //request
412  error = ocspParseResponses(data, length, &n, tbsResponseData);
413  //Any error to report?
414  if(error)
415  return error;
416 
417  //Point to the next field
418  data += n;
419  length -= n;
420 
421  //The TbsResponseData structure may contain an optional field
422  if(length > 0)
423  {
424  //Parse ASN.1 tag
425  error = asn1ReadTag(data, length, &tag);
426  //Failed to decode ASN.1 tag?
427  if(error)
428  return error;
429 
430  //Enforce encoding, class and type
431  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 1);
432 
433  //Check whether the ResponseExtensions field is present
434  if(!error)
435  {
436  //OCSP extensions are based on the extension model employed in X.509
437  //version 3 certificates (refer to RFC 6960, section 4.4)
438  error = ocspParseResponseExtensions(tag.value, tag.length,
439  &tbsResponseData->responseExtensions);
440  //Any error to report?
441  if(error)
442  return error;
443  }
444  }
445 
446  //Successful processing
447  return NO_ERROR;
448 }
449 
450 
451 /**
452  * @brief Parse Version field
453  * @param[in] data Pointer to the ASN.1 structure to parse
454  * @param[in] length Length of the ASN.1 structure
455  * @param[out] totalLength Number of bytes that have been parsed
456  * @param[out] version Information resulting from the parsing process
457  * @return Error code
458  **/
459 
460 error_t ocspParseVersion(const uint8_t *data, size_t length,
461  size_t *totalLength, OcspVersion *version)
462 {
463  error_t error;
464  int32_t value;
465  Asn1Tag tag;
466 
467  //Explicit tagging shall be used to encode version
468  error = asn1ReadTag(data, length, &tag);
469  //Failed to decode ASN.1 tag?
470  if(error)
471  return error;
472 
473  //Enforce encoding, class and type
474  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
475 
476  //Invalid tag?
477  if(error)
478  {
479  //Assume OCSP version 1
481  //Skip the current field
482  *totalLength = 0;
483 
484  //Exit immediately
485  return NO_ERROR;
486  }
487 
488  //Save the total length of the field
489  *totalLength = tag.totalLength;
490 
491  //Read the inner tag
492  error = asn1ReadInt32(tag.value, tag.length, &tag, &value);
493  //Failed to decode ASN.1 tag?
494  if(error)
495  return error;
496 
497  //Save certificate version
499 
500  //Successful processing
501  return NO_ERROR;
502 }
503 
504 
505 /**
506  * @brief Parse ResponderID structure
507  * @param[in] data Pointer to the ASN.1 structure to parse
508  * @param[in] length Length of the ASN.1 structure
509  * @param[out] totalLength Number of bytes that have been parsed
510  * @param[out] responderId Information resulting from the parsing process
511  * @return Error code
512  **/
513 
514 error_t ocspParseResponderId(const uint8_t *data, size_t length,
515  size_t *totalLength, OcspResponderId *responderId)
516 {
517  error_t error;
518  size_t n;
519  Asn1Tag tag;
520 
521  //Explicit tagging shall be used to encode the responder ID
522  error = asn1ReadTag(data, length, &tag);
523  //Failed to decode ASN.1 tag?
524  if(error)
525  return error;
526 
527  //Enforce encoding, class and type
529  return ERROR_INVALID_TAG;
530 
531  //Save the total length of the field
532  *totalLength = tag.totalLength;
533 
534  //Point to the inner value
535  data = tag.value;
536  length = tag.length;
537 
538  //The ResponderID field contains either the name of the responder or
539  //a hash of the responder's public key
540  if(tag.objType == 1)
541  {
542  //Retrieve the name of the responder
543  error = x509ParseName(data, length, &n, &responderId->name);
544  }
545  else if(tag.objType == 2)
546  {
547  //Retrieve the hash of the responder's public key
548  error = asn1ReadOctetString(data, length, &tag);
549 
550  //Check status code
551  if(!error)
552  {
553  responderId->keyHash.value = tag.value;
554  responderId->keyHash.length = tag.length;
555  }
556  }
557  else
558  {
559  //Report an error
560  error = ERROR_INVALID_TYPE;
561  }
562 
563  //Return status code
564  return error;
565 }
566 
567 
568 /**
569  * @brief Parse Responses structure
570  * @param[in] data Pointer to the ASN.1 structure to parse
571  * @param[in] length Length of the ASN.1 structure
572  * @param[out] totalLength Number of bytes that have been parsed
573  * @param[out] tbsResponseData Information resulting from the parsing process
574  * @return Error code
575  **/
576 
577 error_t ocspParseResponses(const uint8_t *data, size_t length,
578  size_t *totalLength, OcspTbsResponseData *tbsResponseData)
579 {
580  error_t error;
581  uint_t i;
582  size_t n;
583  Asn1Tag tag;
584 
585  //The Responses structure is encapsulated within a sequence
586  error = asn1ReadSequence(data, length, &tag);
587  //Failed to decode ASN.1 tag?
588  if(error)
589  return error;
590 
591  //Save the total length of the field
592  *totalLength = tag.totalLength;
593 
594  //Point to the first field of the sequence
595  data = tag.value;
596  length = tag.length;
597 
598  //The basic response contains responses for each of the certificates in a
599  //request
600  for(i = 0; i < OCSP_MAX_RESPONSES && length > 0; i++)
601  {
602  //Parse current response
604  &tbsResponseData->responses[i]);
605  //Any error to report?
606  if(error)
607  return error;
608 
609  //Point to the next response
610  data += n;
611  length -= n;
612  }
613 
614  //Save the number of responses
615  tbsResponseData->numResponses = i;
616 
617  //Successful processing
618  return NO_ERROR;
619 }
620 
621 
622 /**
623  * @brief Parse SingleResponse structure
624  * @param[in] data Pointer to the ASN.1 structure to parse
625  * @param[in] length Length of the ASN.1 structure
626  * @param[out] totalLength Number of bytes that have been parsed
627  * @param[out] singleResponse Information resulting from the parsing process
628  * @return Error code
629  **/
630 
632  size_t *totalLength, OcspSingleResponse *singleResponse)
633 {
634  error_t error;
635  size_t n;
636  Asn1Tag tag;
637 
638  //The SingleResponse structure is encapsulated within a sequence
639  error = asn1ReadSequence(data, length, &tag);
640  //Failed to decode ASN.1 tag?
641  if(error)
642  return error;
643 
644  //Save the total length of the field
645  *totalLength = tag.totalLength;
646 
647  //Point to the first field of the sequence
648  data = tag.value;
649  length = tag.length;
650 
651  //The CertID field contains an identifier of the certificate for which
652  //revocation status information is being provided
653  error = ocspParseCertId(data, length, &n, &singleResponse->certId);
654  //Any error to report?
655  if(error)
656  return error;
657 
658  //Point to the next field
659  data += n;
660  length -= n;
661 
662  //The CertStatus field contains the revocation status of the certificate
663  //(good, revoked, or unknown)
664  error = ocspParseCertStatus(data, length, &n, singleResponse);
665  //Any error to report?
666  if(error)
667  return error;
668 
669  //Point to the next field
670  data += n;
671  length -= n;
672 
673  //The ThisUpdate field indicates the most recent time at which the status
674  //being indicated is known by the responder to have been correct
675  error = x509ParseTime(data, length, &n, &singleResponse->thisUpdate);
676  //Any error to report?
677  if(error)
678  return error;
679 
680  //Point to the next field
681  data += n;
682  length -= n;
683 
684  //The SingleResponse structure may contain optional fields
685  if(length > 0)
686  {
687  //Parse ASN.1 tag
688  error = asn1ReadTag(data, length, &tag);
689  //Failed to decode ASN.1 tag?
690  if(error)
691  return error;
692 
693  //Enforce encoding, class and type
694  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
695 
696  //Check whether the NextUpdate field is present
697  if(!error)
698  {
699  //The NextUpdate field indicates the time at or before which newer
700  //information will be available about the status of the certificate
701  error = x509ParseTime(tag.value, tag.length, &n,
702  &singleResponse->nextUpdate);
703  //Any error to report?
704  if(error)
705  return error;
706 
707  //Point to the next field
708  data += tag.totalLength;
709  length -= tag.totalLength;
710  }
711  }
712 
713  //The SingleResponse structure may contain optional fields
714  if(length > 0)
715  {
716  //Parse ASN.1 tag
717  error = asn1ReadTag(data, length, &tag);
718  //Failed to decode ASN.1 tag?
719  if(error)
720  return error;
721 
722  //Enforce encoding, class and type
723  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 1);
724 
725  //Check whether the SingleExtensions field is present
726  if(!error)
727  {
728  //OCSP extensions are based on the extension model employed in X.509
729  //version 3 certificates (refer to RFC 6960, section 4.4)
730  error = ocspParseSingleExtensions(tag.value, tag.length,
731  &singleResponse->singleExtensions);
732  //Any error to report?
733  if(error)
734  return error;
735  }
736  }
737 
738  //Successful processing
739  return NO_ERROR;
740 }
741 
742 
743 /**
744  * @brief Parse CertID structure
745  * @param[in] data Pointer to the ASN.1 structure to parse
746  * @param[in] length Length of the ASN.1 structure
747  * @param[out] totalLength Number of bytes that have been parsed
748  * @param[out] certId Information resulting from the parsing process
749  * @return Error code
750  **/
751 
752 error_t ocspParseCertId(const uint8_t *data, size_t length,
753  size_t *totalLength, OcspCertId *certId)
754 {
755  error_t error;
756  size_t n;
757  Asn1Tag tag;
758 
759  //The CertID structure is encapsulated within a sequence
760  error = asn1ReadSequence(data, length, &tag);
761  //Failed to decode ASN.1 tag?
762  if(error)
763  return error;
764 
765  //Save the total length of the field
766  *totalLength = tag.totalLength;
767 
768  //Point to the first field of the sequence
769  data = tag.value;
770  length = tag.length;
771 
772  //Parse HashAlgorithm structure
773  error = ocspParseHashAlgo(data, length, &n, certId);
774  //Any error to report?
775  if(error)
776  return error;
777 
778  //Point to the next field
779  data += n;
780  length -= n;
781 
782  //Parse IssuerNameHash field
783  error = asn1ReadOctetString(data, length, &tag);
784  //Failed to decode ASN.1 tag?
785  if(error)
786  return error;
787 
788  //Save the hash of the issuer's distinguished name (DN)
789  certId->issuerNameHash.value = tag.value;
790  certId->issuerNameHash.length = tag.length;
791 
792  //Point to the next field
793  data += tag.totalLength;
794  length -= tag.totalLength;
795 
796  //Parse IssuerKeyHash field
797  error = asn1ReadOctetString(data, length, &tag);
798  //Failed to decode ASN.1 tag?
799  if(error)
800  return error;
801 
802  //Save the hash of the issuer's public key
803  certId->issuerKeyHash.value = tag.value;
804  certId->issuerKeyHash.length = tag.length;
805 
806  //Point to the next field
807  data += tag.totalLength;
808  length -= tag.totalLength;
809 
810  //Parse SerialNumber field
811  error = asn1ReadTag(data, length, &tag);
812  //Failed to decode ASN.1 tag?
813  if(error)
814  return error;
815 
816  //Enforce encoding, class and type
817  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
819  //Invalid tag?
820  if(error)
821  return error;
822 
823  //Save serial number
824  certId->serialNumber.value = tag.value;
825  certId->serialNumber.length = tag.length;
826 
827  //Successful processing
828  return NO_ERROR;
829 }
830 
831 
832 /**
833  * @brief Parse HashAlgorithm structure
834  * @param[in] data Pointer to the ASN.1 structure to parse
835  * @param[in] length Length of the ASN.1 structure
836  * @param[out] totalLength Number of bytes that have been parsed
837  * @param[out] certId Information resulting from the parsing process
838  * @return Error code
839  **/
840 
841 error_t ocspParseHashAlgo(const uint8_t *data, size_t length,
842  size_t *totalLength, OcspCertId *certId)
843 {
844  error_t error;
845  Asn1Tag tag;
846 
847  //The HashAlgorithm structure is encapsulated within a sequence
848  error = asn1ReadSequence(data, length, &tag);
849  //Failed to decode ASN.1 tag?
850  if(error)
851  return error;
852 
853  //Save the total length of the field
854  *totalLength = tag.totalLength;
855 
856  //Point to the first field of the sequence
857  data = tag.value;
858  length = tag.length;
859 
860  //Parse hash algorithm OID
861  error = asn1ReadOid(data, length, &tag);
862  //Failed to decode ASN.1 tag?
863  if(error)
864  return error;
865 
866  //Save hash algorithm OID
867  certId->hashAlgo.value = tag.value;
868  certId->hashAlgo.length = tag.length;
869 
870  //Successful processing
871  return NO_ERROR;
872 }
873 
874 
875 /**
876  * @brief Parse CertStatus structure
877  * @param[in] data Pointer to the ASN.1 structure to parse
878  * @param[in] length Length of the ASN.1 structure
879  * @param[out] totalLength Number of bytes that have been parsed
880  * @param[out] singleResponse Information resulting from the parsing process
881  * @return Error code
882  **/
883 
884 error_t ocspParseCertStatus(const uint8_t *data, size_t length,
885  size_t *totalLength, OcspSingleResponse *singleResponse)
886 {
887  error_t error;
888  Asn1Tag tag;
889 
890  //Implicit tagging shall be used to encode the certificate status
891  error = asn1ReadTag(data, length, &tag);
892  //Failed to decode ASN.1 tag?
893  if(error)
894  return error;
895 
896  //Enforce encoding, class and type
898  return ERROR_INVALID_TAG;
899 
900  //Save the total length of the field
901  *totalLength = tag.totalLength;
902 
903  //Check certificate status value
904  if(tag.objType == 0)
905  {
906  //The "good" state indicates a positive response to the status inquiry
907  singleResponse->certStatus = OCSP_CERT_STATUS_GOOD;
908  }
909  else if(tag.objType == 1 && tag.constructed)
910  {
911  //The "revoked" state indicates that the certificate has been revoked,
912  //either temporarily (the revocation reason is certificateHold) or
913  //permanently
914  singleResponse->certStatus = OCSP_CERT_STATUS_REVOKED;
915 
916  //Parse RevokedInfo structure
917  error = ocspParseRevokedInfo(tag.value, tag.length,
918  &singleResponse->revokedInfo);
919  }
920  else if(tag.objType == 2)
921  {
922  //The "unknown" state indicates that the responder doesn't know about
923  //the certificate being requested, usually because the request indicates
924  //an unrecognized issuer that is not served by this responder
925  singleResponse->certStatus = OCSP_CERT_STATUS_UNKNOWN;
926  }
927  else
928  {
929  //Invalid status
930  error = ERROR_INVALID_TYPE;
931  }
932 
933  //Return status code
934  return error;
935 }
936 
937 
938 /**
939  * @brief Parse RevokedInfo structure
940  * @param[in] data Pointer to the ASN.1 structure to parse
941  * @param[in] length Length of the ASN.1 structure
942  * @param[out] revokedInfo Information resulting from the parsing process
943  * @return Error code
944  **/
945 
946 error_t ocspParseRevokedInfo(const uint8_t *data, size_t length,
947  OcspRevokedInfo *revokedInfo)
948 {
949  error_t error;
950  size_t n;
951  Asn1Tag tag;
952 
953  //The RevocationTime field indicates the time at which the certificate was
954  //revoked or placed on hold
955  error = x509ParseTime(data, length, &n, &revokedInfo->revocationTime);
956  //Failed to decode ASN.1 tag?
957  if(error)
958  return error;
959 
960  //Point to the next field
961  data += n;
962  length -= n;
963 
964  //The RevokedInfo structure may contain an optional field
965  if(length > 0)
966  {
967  //Parse ASN.1 tag
968  error = asn1ReadTag(data, length, &tag);
969  //Failed to decode ASN.1 tag?
970  if(error)
971  return error;
972 
973  //Enforce encoding, class and type
974  error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
975 
976  //Check whether the RevocationReason field is present
977  if(!error)
978  {
979  //Parse RevocationReason field indicates the reason why the certificate
980  //was revoked
981  error = ocspParseRevocationReason(tag.value, tag.length,
982  &revokedInfo->revocationReason);
983  //Any error to report?
984  if(error)
985  return error;
986  }
987  }
988 
989  //Successful processing
990  return NO_ERROR;
991 }
992 
993 
994 /**
995  * @brief Parse RevocationReason field
996  * @param[in] data Pointer to the ASN.1 structure to parse
997  * @param[in] length Length of the ASN.1 structure
998  * @param[out] revocationReason Reason why the certificate was revoked
999  * @return Error code
1000  **/
1001 
1003  X509CrlReasons *revocationReason)
1004 {
1005  error_t error;
1006  Asn1Tag tag;
1007 
1008  //Read ASN.1 tag
1009  error = asn1ReadTag(data, length, &tag);
1010  //Failed to decode ASN.1 tag?
1011  if(error)
1012  return error;
1013 
1014  //Enforce encoding, class and type
1015  error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL,
1017  //Invalid tag?
1018  if(error)
1019  return error;
1020 
1021  //Check the length of the field
1022  if(tag.length != 1)
1023  return ERROR_INVALID_SYNTAX;
1024 
1025  //Parse RevocationReason field indicates the reason why the certificate
1026  //was revoked
1027  *revocationReason = (X509CrlReasons) tag.value[0];
1028 
1029  //Successful processing
1030  return NO_ERROR;
1031 }
1032 
1033 
1034 /**
1035  * @brief Parse Certs structure
1036  * @param[in] data Pointer to the ASN.1 structure to parse
1037  * @param[in] length Length of the ASN.1 structure
1038  * @param[out] certs Information resulting from the parsing process
1039  * @return Error code
1040  **/
1041 
1042 error_t ocspParseCerts(const uint8_t *data, size_t length,
1043  OcspCerts *certs)
1044 {
1045  error_t error;
1046  Asn1Tag tag;
1047 
1048  //The HashAlgorithm structure is encapsulated within a sequence
1049  error = asn1ReadSequence(data, length, &tag);
1050  //Failed to decode ASN.1 tag?
1051  if(error)
1052  return error;
1053 
1054  //Raw contents of the ASN.1 sequence
1055  certs->raw.value = tag.value;
1056  certs->raw.length = tag.length;
1057 
1058  //Successful processing
1059  return NO_ERROR;
1060 }
1061 
1062 
1063 /**
1064  * @brief Parse ResponseExtensions structure
1065  * @param[in] data Pointer to the ASN.1 structure to parse
1066  * @param[in] length Length of the ASN.1 structure
1067  * @param[out] responseExtensions Information resulting from the parsing process
1068  * @return Error code
1069  **/
1070 
1072  OcspExtensions *responseExtensions)
1073 {
1074  error_t error;
1075  size_t n;
1076  Asn1Tag tag;
1077  X509Extension extension;
1078 
1079  //This field is a sequence of one or more OCSP extensions
1080  error = asn1ReadSequence(data, length, &tag);
1081  //Failed to decode ASN.1 tag?
1082  if(error)
1083  return error;
1084 
1085  //Raw contents of the ASN.1 sequence
1086  responseExtensions->raw.value = tag.value;
1087  responseExtensions->raw.length = tag.length;
1088 
1089  //Point to the first item of the sequence
1090  data = tag.value;
1091  length = tag.length;
1092 
1093  //OCSP extension are based on the extension model employed in X.509 version 3
1094  //certificates (refer to RFC 6960, section 4.4)
1095  while(length > 0)
1096  {
1097  //Each extension includes an OID and a value
1098  error = x509ParseExtension(data, length, &n, &extension);
1099  //Any error to report?
1100  if(error)
1101  return error;
1102 
1103  //Jump to the next extension
1104  data += n;
1105  length -= n;
1106 
1107  //Test if the current extension is a duplicate
1108  error = x509CheckDuplicateExtension(extension.oid.value,
1109  extension.oid.length, data, length);
1110  //Duplicate extension found?
1111  if(error)
1112  return error;
1113 
1114  //Check extension identifier
1115  if(!oidComp(extension.oid.value, extension.oid.length,
1117  {
1118  //Parse Nonce extension
1119  error = ocspParseNonceExtension(extension.critical,
1120  extension.data.value, extension.data.length,
1121  &responseExtensions->nonce);
1122  }
1123  else
1124  {
1125  //Unrecognized extensions must be ignored, unless they have the
1126  //critical flag set and are not understood refer to RFC 6960,
1127  //section 4.1.2)
1128  if(extension.critical)
1129  {
1131  }
1132  }
1133 
1134  //Any parsing error?
1135  if(error)
1136  return error;
1137  }
1138 
1139  //Successful processing
1140  return NO_ERROR;
1141 }
1142 
1143 
1144 /**
1145  * @brief Parse SingleExtensions structure
1146  * @param[in] data Pointer to the ASN.1 structure to parse
1147  * @param[in] length Length of the ASN.1 structure
1148  * @param[out] singleExtensions Information resulting from the parsing process
1149  * @return Error code
1150  **/
1151 
1153  OcspSingleExtensions *singleExtensions)
1154 {
1155  error_t error;
1156  size_t n;
1157  Asn1Tag tag;
1158  X509Extension extension;
1159 
1160  //This field is a sequence of one or more OCSP extensions
1161  error = asn1ReadSequence(data, length, &tag);
1162  //Failed to decode ASN.1 tag?
1163  if(error)
1164  return error;
1165 
1166  //Raw contents of the ASN.1 sequence
1167  singleExtensions->raw.value = tag.value;
1168  singleExtensions->raw.length = tag.length;
1169 
1170  //Point to the first item of the sequence
1171  data = tag.value;
1172  length = tag.length;
1173 
1174  //OCSP extension are based on the extension model employed in X.509 version 3
1175  //certificates (refer to RFC 6960, section 4.4)
1176  while(length > 0)
1177  {
1178  //Each extension includes an OID and a value
1179  error = x509ParseExtension(data, length, &n, &extension);
1180  //Any error to report?
1181  if(error)
1182  return error;
1183 
1184  //Jump to the next extension
1185  data += n;
1186  length -= n;
1187 
1188  //Test if the current extension is a duplicate
1189  error = x509CheckDuplicateExtension(extension.oid.value,
1190  extension.oid.length, data, length);
1191  //Duplicate extension found?
1192  if(error)
1193  return error;
1194 
1195  //Unrecognized extensions must be ignored, unless they have the critical
1196  //flag set and are not understood refer to RFC 6960, section 4.1.2)
1197  if(extension.critical)
1198  {
1200  }
1201  }
1202 
1203  //Successful processing
1204  return NO_ERROR;
1205 }
1206 
1207 
1208 /**
1209  * @brief Parse Nonce extension
1210  * @param[in] critical Critical extension flag
1211  * @param[in] data Pointer to the ASN.1 structure to parse
1212  * @param[in] length Length of the ASN.1 structure
1213  * @param[out] nonce Information resulting from the parsing process
1214  * @return Error code
1215  **/
1216 
1218  size_t length, X509OctetString *nonce)
1219 {
1220  error_t error;
1221  Asn1Tag tag;
1222 
1223  //The Nonce extension is used to cryptographically binds a request and
1224  //a response to prevent replay attacks (refer to RFC 8954, section 2.1)
1225  error = asn1ReadOctetString(data, length, &tag);
1226  //Failed to decode ASN.1 tag?
1227  if(error)
1228  return error;
1229 
1230  //Save the nonce
1231  nonce->value = tag.value;
1232  nonce->length = tag.length;
1233 
1234  //Successful processing
1235  return NO_ERROR;
1236 }
1237 
1238 #endif
error_t asn1ReadOctetString(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an octet string from the input stream.
Definition: asn1.c:190
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:52
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:163
error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass, uint_t objType)
Enforce the type of a specified tag.
Definition: asn1.c:653
error_t asn1ReadOid(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an object identifier from the input stream.
Definition: asn1.c:218
error_t asn1ReadInt32(const uint8_t *data, size_t length, Asn1Tag *tag, int32_t *value)
Read a 32-bit integer from the input stream.
Definition: asn1.c:285
error_t asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
Display an ASN.1 data object.
Definition: asn1.c:706
ASN.1 (Abstract Syntax Notation One)
@ ASN1_TYPE_ENUMERATED
Definition: asn1.h:78
@ ASN1_TYPE_INTEGER
Definition: asn1.h:70
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
uint8_t version
Definition: coap_common.h:177
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_UNSUPPORTED_EXTENSION
Definition: error.h:244
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ERROR_INVALID_TAG
Definition: error.h:114
@ ERROR_INVALID_VERSION
Definition: error.h:118
uint8_t data[]
Definition: ethernet.h:222
uint8_t critical
Definition: ike.h:1281
uint16_t totalLength
Definition: ipv4.h:292
const uint8_t PKIX_OCSP_BASIC_OID[9]
Definition: ocsp_common.c:42
const uint8_t PKIX_OCSP_NONCE_OID[9]
Definition: ocsp_common.c:44
OcspVersion
OCSP versions.
Definition: ocsp_common.h:105
@ OCSP_VERSION_1
Definition: ocsp_common.h:106
OcspResponseStatus
OCSP response status.
Definition: ocsp_common.h:115
@ OCSP_RESP_STATUS_SUCCESSFUL
Response has valid confirmations.
Definition: ocsp_common.h:116
@ OCSP_CERT_STATUS_GOOD
Definition: ocsp_common.h:131
@ OCSP_CERT_STATUS_REVOKED
Definition: ocsp_common.h:132
@ OCSP_CERT_STATUS_UNKNOWN
Definition: ocsp_common.h:133
error_t ocspParseCertStatus(const uint8_t *data, size_t length, size_t *totalLength, OcspSingleResponse *singleResponse)
Parse CertStatus structure.
error_t ocspParseResponseBytes(const uint8_t *data, size_t length, OcspResponse *response)
Parse ResponseBytes structure.
error_t ocspParseSingleExtensions(const uint8_t *data, size_t length, OcspSingleExtensions *singleExtensions)
Parse SingleExtensions structure.
error_t ocspParseRevokedInfo(const uint8_t *data, size_t length, OcspRevokedInfo *revokedInfo)
Parse RevokedInfo structure.
error_t ocspParseSingleResponse(const uint8_t *data, size_t length, size_t *totalLength, OcspSingleResponse *singleResponse)
Parse SingleResponse structure.
error_t ocspParseResponse(const uint8_t *data, size_t length, OcspResponse *response)
Parse OCSPResponse structure.
error_t ocspParseResponses(const uint8_t *data, size_t length, size_t *totalLength, OcspTbsResponseData *tbsResponseData)
Parse Responses structure.
error_t ocspParseResponseExtensions(const uint8_t *data, size_t length, OcspExtensions *responseExtensions)
Parse ResponseExtensions structure.
error_t ocspParseCerts(const uint8_t *data, size_t length, OcspCerts *certs)
Parse Certs structure.
error_t ocspParseNonceExtension(bool_t critical, const uint8_t *data, size_t length, X509OctetString *nonce)
Parse Nonce extension.
error_t ocspParseVersion(const uint8_t *data, size_t length, size_t *totalLength, OcspVersion *version)
Parse Version field.
error_t ocspParseBasicResponse(const uint8_t *data, size_t length, OcspBasicResponse *basicResponse)
Parse BasicOCSPResponse structure.
error_t ocspParseTbsResponseData(const uint8_t *data, size_t length, size_t *totalLength, OcspTbsResponseData *tbsResponseData)
Parse TbsResponseData structure.
error_t ocspParseHashAlgo(const uint8_t *data, size_t length, size_t *totalLength, OcspCertId *certId)
Parse HashAlgorithm structure.
error_t ocspParseRevocationReason(const uint8_t *data, size_t length, X509CrlReasons *revocationReason)
Parse RevocationReason field.
error_t ocspParseResponseStatus(const uint8_t *data, size_t length, size_t *totalLength, OcspResponseStatus *status)
Parse ResponseStatus field.
error_t ocspParseResponderId(const uint8_t *data, size_t length, size_t *totalLength, OcspResponderId *responderId)
Parse ResponderID structure.
error_t ocspParseCertId(const uint8_t *data, size_t length, size_t *totalLength, OcspCertId *certId)
Parse CertID structure.
OCSP response parsing.
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
OID (Object Identifier)
#define osMemset(p, value, length)
Definition: os_port.h:135
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
ASN.1 tag.
Definition: asn1.h:102
size_t totalLength
Definition: asn1.h:108
const uint8_t * value
Definition: asn1.h:107
uint_t objClass
Definition: asn1.h:104
uint_t objType
Definition: asn1.h:105
bool_t constructed
Definition: asn1.h:103
size_t length
Definition: asn1.h:106
BasicOCSPResponse structure.
Definition: ocsp_common.h:275
X509OctetString signature
Definition: ocsp_common.h:278
OcspTbsResponseData tbsResponseData
Definition: ocsp_common.h:276
X509SignAlgoId signatureAlgo
Definition: ocsp_common.h:277
CertID structure.
Definition: ocsp_common.h:142
X509OctetString serialNumber
Definition: ocsp_common.h:146
X509OctetString hashAlgo
Definition: ocsp_common.h:143
X509OctetString issuerNameHash
Definition: ocsp_common.h:144
X509OctetString issuerKeyHash
Definition: ocsp_common.h:145
OcspCerts structure.
Definition: ocsp_common.h:265
X509OctetString raw
Definition: ocsp_common.h:266
OCSP extensions.
Definition: ocsp_common.h:176
X509OctetString nonce
Definition: ocsp_common.h:178
X509OctetString raw
Definition: ocsp_common.h:177
ResponderID structure.
Definition: ocsp_common.h:238
X509OctetString keyHash
Definition: ocsp_common.h:240
OCSPResponse structure.
Definition: ocsp_common.h:288
X509OctetString raw
Definition: ocsp_common.h:289
OcspBasicResponse basicResponse
Definition: ocsp_common.h:292
X509OctetString responseType
Definition: ocsp_common.h:291
OcspResponseStatus responseStatus
Definition: ocsp_common.h:290
RevokedInfo structure.
Definition: ocsp_common.h:212
X509CrlReasons revocationReason
Definition: ocsp_common.h:214
DateTime revocationTime
Definition: ocsp_common.h:213
Single request/response extensions.
Definition: ocsp_common.h:155
X509OctetString raw
Definition: ocsp_common.h:156
SingleResponse structure.
Definition: ocsp_common.h:223
OcspRevokedInfo revokedInfo
Definition: ocsp_common.h:226
OcspCertStatus certStatus
Definition: ocsp_common.h:225
OcspCertId certId
Definition: ocsp_common.h:224
OcspSingleExtensions singleExtensions
Definition: ocsp_common.h:229
TbsResponseData structure.
Definition: ocsp_common.h:249
OcspResponderId responderId
Definition: ocsp_common.h:252
OcspVersion version
Definition: ocsp_common.h:251
X509OctetString raw
Definition: ocsp_common.h:250
OcspSingleResponse responses[OCSP_MAX_RESPONSES]
Definition: ocsp_common.h:255
OcspExtensions responseExtensions
Definition: ocsp_common.h:256
X.509 certificate extension.
Definition: x509_common.h:984
X509OctetString data
Definition: x509_common.h:987
bool_t critical
Definition: x509_common.h:986
X509OctetString oid
Definition: x509_common.h:985
Octet string.
Definition: x509_common.h:646
const uint8_t * value
Definition: x509_common.h:647
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369
error_t x509ParseExtension(const uint8_t *data, size_t length, size_t *totalLength, X509Extension *extension)
Parse X.509 certificate extension.
error_t x509CheckDuplicateExtension(const uint8_t *oid, size_t oidLen, const uint8_t *data, size_t length)
Check whether the specified extension is a duplicate.
X.509 extension parsing.
error_t x509ParseName(const uint8_t *data, size_t length, size_t *totalLength, X509Name *name)
Parse Name structure.
error_t x509ParseTime(const uint8_t *data, size_t length, size_t *totalLength, DateTime *dateTime)
Parse UTCTime or GeneralizedTime field.
X.509 certificate parsing.
X509CrlReasons
CRL reasons.
Definition: x509_common.h:559
error_t x509ParseSignatureValue(const uint8_t *data, size_t length, size_t *totalLength, X509OctetString *signature)
Parse SignatureValue field.
error_t x509ParseSignatureAlgo(const uint8_t *data, size_t length, size_t *totalLength, X509SignAlgoId *signatureAlgo)
Parse SignatureAlgorithm structure.