asn1.c
Go to the documentation of this file.
1 /**
2  * @file asn1.c
3  * @brief ASN.1 (Abstract Syntax Notation One)
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 CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "encoding/asn1.h"
37 #include "encoding/oid.h"
38 #include "debug.h"
39 
40 //Check crypto library configuration
41 #if (ASN1_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Read an ASN.1 tag from the input stream
46  * @param[in] data Input stream where to read the tag
47  * @param[in] length Number of bytes available in the input stream
48  * @param[out] tag Structure describing the ASN.1 tag
49  * @return Error code
50  **/
51 
52 error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
53 {
54  uint_t i;
55  uint_t n;
56 
57  //Make sure the identifier octet is present
58  if(length == 0)
59  return ERROR_INVALID_TAG;
60 
61  //Save the class of the ASN.1 tag
62  tag->objClass = data[0] & ASN1_CLASS_MASK;
63  //Primitive or constructed encoding?
65 
66  //Check the tag number
67  if((data[0] & ASN1_TAG_NUMBER_MASK) < 31)
68  {
69  //Tag number is in the range 0 to 30
70  tag->objType = data[0] & ASN1_TAG_NUMBER_MASK;
71  //Point to the tag length field
72  i = 1;
73  }
74  else
75  {
76  //If the tag number is greater than or equal to 31,
77  //the subsequent octets will encode the tag number
78  tag->objType = 0;
79 
80  //Decode the tag number
81  for(i = 1; ; i++)
82  {
83  //The field cannot exceed 5 bytes
84  if(i > (sizeof(tag->objType) + 1))
85  return ERROR_INVALID_TAG;
86  //Insufficient number of bytes to decode the tag number?
87  if(!(length - i))
88  return ERROR_INVALID_TAG;
89 
90  //Update the tag number with bits 7 to 1
91  tag->objType = (tag->objType << 7) | (data[i] & 0x7F);
92 
93  //Bit 8 shall be set unless it is the last octet
94  if(!(data[i] & 0x80))
95  break;
96  }
97  //Point to the tag length field
98  i++;
99  }
100 
101  //Insufficient number of bytes to decode the tag length?
102  if(!(length - i))
103  return ERROR_INVALID_TAG;
104 
105  //Short form is used?
106  if(data[i] < 128)
107  {
108  //Bits 7 to 1 encode the number of bytes in the contents
109  tag->length = data[i];
110  //Point to the contents of the tag
111  i++;
112  }
113  //Long form is used?
114  else if(data[i] > 128 && data[i] < 255)
115  {
116  //Bits 7 to 1 encode the number of octets in the length field
117  n = data[i] & 0x7F;
118 
119  //The field cannot exceed 4 bytes
120  if(n > sizeof(tag->length))
121  return ERROR_INVALID_TAG;
122  //Insufficient number of bytes to decode the tag length?
123  if((length - i) < n)
124  return ERROR_INVALID_TAG;
125 
126  //Clear the tag length
127  tag->length = 0;
128 
129  //Read the subsequent octets
130  for(i++; n > 0; n--)
131  {
132  tag->length = (tag->length << 8) | data[i++];
133  }
134  }
135  //Indefinite form is used?
136  else
137  {
138  //Indefinite form is not supported
139  return ERROR_INVALID_TAG;
140  }
141 
142  //Save the pointer to the tag contents
143  tag->value = data + i;
144  //Check the length of tag
145  if((length - i) < tag->length)
146  return ERROR_INVALID_TAG;
147 
148  //Total length occupied by the ASN.1 tag in the input stream
149  tag->totalLength = i + tag->length;
150  //ASN.1 tag successfully decoded
151  return NO_ERROR;
152 }
153 
154 
155 /**
156  * @brief Read an ASN.1 sequence from the input stream
157  * @param[in] data Input stream where to read the tag
158  * @param[in] length Number of bytes available in the input stream
159  * @param[out] tag Structure describing the ASN.1 tag
160  * @return Error code
161  **/
162 
163 error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
164 {
165  error_t error;
166 
167  //Read ASN.1 tag
168  error = asn1ReadTag(data, length, tag);
169 
170  //Check status code
171  if(!error)
172  {
173  //Enforce encoding, class and type
175  }
176 
177  //Return status code
178  return error;
179 }
180 
181 
182 /**
183  * @brief Read an octet string from the input stream
184  * @param[in] data Input stream where to read the tag
185  * @param[in] length Number of bytes available in the input stream
186  * @param[out] tag Structure describing the ASN.1 tag
187  * @return Error code
188  **/
189 
190 error_t asn1ReadOctetString(const uint8_t *data, size_t length, Asn1Tag *tag)
191 {
192  error_t error;
193 
194  //Read ASN.1 tag
195  error = asn1ReadTag(data, length, tag);
196 
197  //Check status code
198  if(!error)
199  {
200  //Enforce encoding, class and type
203  }
204 
205  //Return status code
206  return error;
207 }
208 
209 
210 /**
211  * @brief Read an object identifier from the input stream
212  * @param[in] data Input stream where to read the tag
213  * @param[in] length Number of bytes available in the input stream
214  * @param[out] tag Structure describing the ASN.1 tag
215  * @return Error code
216  **/
217 
218 error_t asn1ReadOid(const uint8_t *data, size_t length, Asn1Tag *tag)
219 {
220  error_t error;
221 
222  //Read ASN.1 tag
223  error = asn1ReadTag(data, length, tag);
224 
225  //Check status code
226  if(!error)
227  {
228  //Enforce encoding, class and type
231  }
232 
233  //Return status code
234  return error;
235 }
236 
237 
238 /**
239  * @brief Read a boolean from the input stream
240  * @param[in] data Input stream where to read the tag
241  * @param[in] length Number of bytes available in the input stream
242  * @param[out] tag Structure describing the ASN.1 tag
243  * @param[out] value Boolean value
244  * @return Error code
245  **/
246 
247 error_t asn1ReadBoolean(const uint8_t *data, size_t length, Asn1Tag *tag,
248  bool_t *value)
249 {
250  error_t error;
251 
252  //Read ASN.1 tag
253  error = asn1ReadTag(data, length, tag);
254  //Failed to decode ASN.1 tag?
255  if(error)
256  return error;
257 
258  //Enforce encoding, class and type
260  //Invalid tag?
261  if(error)
262  return error;
263 
264  //Make sure the length of the boolean is valid
265  if(tag->length != 1)
266  return ERROR_INVALID_LENGTH;
267 
268  //Read the value of the boolean
269  *value = tag->value[0] ? TRUE : FALSE;
270 
271  //ASN.1 tag successfully decoded
272  return NO_ERROR;
273 }
274 
275 
276 /**
277  * @brief Read a 32-bit integer from the input stream
278  * @param[in] data Input stream where to read the tag
279  * @param[in] length Number of bytes available in the input stream
280  * @param[out] tag Structure describing the ASN.1 tag
281  * @param[out] value Integer value
282  * @return Error code
283  **/
284 
285 error_t asn1ReadInt32(const uint8_t *data, size_t length, Asn1Tag *tag,
286  int32_t *value)
287 {
288  error_t error;
289  size_t i;
290 
291  //Read ASN.1 tag
292  error = asn1ReadTag(data, length, tag);
293  //Failed to decode ASN.1 tag?
294  if(error)
295  return error;
296 
297  //Enforce encoding, class and type
299  //Invalid tag?
300  if(error)
301  return error;
302 
303  //The contents shall consist of one or more octets
304  if(tag->length < 1 || tag->length > 4)
305  return ERROR_INVALID_TAG;
306 
307  //The contents octets shall be a two's complement binary
308  //number equal to the integer value
309  *value = (tag->value[0] & 0x80) ? -1 : 0;
310 
311  //Process contents octets
312  for(i = 0; i < tag->length; i++)
313  {
314  //Rotate left operation
315  *value <<= 8;
316  //Reconstruct integer value
317  *value |= tag->value[i];
318  }
319 
320  //ASN.1 tag successfully decoded
321  return NO_ERROR;
322 }
323 
324 
325 /**
326  * @brief Write an ASN.1 tag
327  * @param[in] tag Structure describing the ASN.1 tag
328  * @param[in] reverse Use reverse encoding
329  * @param[out] data Output stream where to write the tag (optional parameter)
330  * @param[out] written Number of bytes written to the output stream (optional parameter)
331  * @return Error code
332  **/
333 
334 error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data,
335  size_t *written)
336 {
337  size_t i;
338  size_t m;
339  size_t n;
340 
341  //Compute the number of octets that are necessary to encode the tag number
342  if(tag->objType < 31)
343  {
344  m = 0;
345  }
346  else if(tag->objType < 128)
347  {
348  m = 1;
349  }
350  else if(tag->objType < 16384)
351  {
352  m = 2;
353  }
354  else if(tag->objType < 2097152)
355  {
356  m = 3;
357  }
358  else if(tag->objType < 268435456)
359  {
360  m = 4;
361  }
362  else
363  {
364  m = 5;
365  }
366 
367  //Compute the number of octets that are necessary to encode the length field
368  if(tag->length < 128)
369  {
370  n = 0;
371  }
372  else if(tag->length < 256)
373  {
374  n = 1;
375  }
376  else if(tag->length < 65536)
377  {
378  n = 2;
379  }
380  else if(tag->length < 16777216)
381  {
382  n = 3;
383  }
384  else
385  {
386  n = 4;
387  }
388 
389  //Valid output stream?
390  if(data != NULL)
391  {
392  //Use reverse encoding?
393  if(reverse)
394  {
395  //Any data to copy?
396  if(tag->value != NULL && tag->length > 0)
397  {
398  //Make room for the data
399  data -= tag->length;
400  //Copy data
401  osMemmove(data, tag->value, tag->length);
402  }
403 
404  //Move backward
405  data -= m + n + 2;
406  }
407  else
408  {
409  //Any data to copy?
410  if(tag->value != NULL && tag->length > 0)
411  {
412  //Copy data
413  osMemmove(data + m + n + 2, tag->value, tag->length);
414  }
415  }
416 
417  //Save the class of the ASN.1 tag
418  data[0] = tag->objClass;
419 
420  //Primitive or constructed encoding?
421  if(tag->constructed)
423 
424  //Encode the tag number
425  if(m == 0)
426  {
427  //Tag number is in the range 0 to 30
428  data[0] |= tag->objType;
429  }
430  else
431  {
432  //The tag number is greater than or equal to 31
434 
435  //The subsequent octets will encode the tag number
436  for(i = 0; i < m; i++)
437  {
438  //Bits 7 to 1 encode the tag number
439  data[m - i] = (tag->objType >> (i * 7)) & 0x7F;
440 
441  //Bit 8 of each octet shall be set to one unless it is the
442  //last octet of the identifier octets
443  if(i != 0)
444  data[m - i] |= 0x80;
445  }
446  }
447 
448  //Encode the length field
449  if(n == 0)
450  {
451  //Use short form encoding
452  data[1 + m] = tag->length & 0x7F;
453  }
454  else
455  {
456  //Bits 7 to 1 encode the number of octets in the length field
457  data[1 + m] = 0x80 | (n & 0x7F);
458 
459  //The subsequent octets will encode the length field
460  for(i = 0; i < n; i++)
461  {
462  data[1 + m + n - i] = (tag->length >> (i * 8)) & 0xFF;
463  }
464  }
465  }
466 
467  //Total length occupied by the ASN.1 tag
468  tag->totalLength = tag->length + m + n + 2;
469 
470  //The last parameter is optional
471  if(written != NULL)
472  {
473  //Number of bytes written to the output stream
474  *written = m + n + 2;
475 
476  //Any data copied?
477  if(tag->value != NULL)
478  *written += tag->length;
479  }
480 
481  //Successful processing
482  return NO_ERROR;
483 }
484 
485 
486 /**
487  * @brief Write a 32-bit integer to the output stream
488  * @param[in] value Integer value
489  * @param[in] reverse Use reverse encoding
490  * @param[out] data Output stream where to write the tag (optional parameter)
491  * @param[out] written Number of bytes written to the output stream
492  * @return Error code
493  **/
494 
495 error_t asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data,
496  size_t *written)
497 {
498  size_t i;
499  size_t n;
500  uint16_t msb;
501 
502  //An integer value is always encoded in the smallest possible number of
503  //octets
504  for(n = 4; n > 1; n--)
505  {
506  //Retrieve the upper 9 bits
507  msb = (value >> (n * 8 - 9)) & 0x01FF;
508 
509  //The upper 9 bits shall not have the same value (all 0 or all 1)
510  if(msb != 0x0000 && msb != 0x01FF)
511  break;
512  }
513 
514  //Valid output stream?
515  if(data != NULL)
516  {
517  //Use reverse encoding?
518  if(reverse)
519  data -= n + 2;
520 
521  //Write tag type
523  //Write tag length
524  data[1] = n & 0xFF;
525 
526  //Write contents octets
527  for(i = 0; i < n; i++)
528  {
529  data[1 + n - i] = (value >> (i * 8)) & 0xFF;
530  }
531  }
532 
533  //Number of bytes written to the output stream
534  if(written != NULL)
535  *written = n + 2;
536 
537  //Successful processing
538  return NO_ERROR;
539 }
540 
541 
542 #if (MPI_SUPPORT == ENABLED)
543 
544 /**
545  * @brief Read a multiple-precision integer from the input stream
546  * @param[in] data Input stream where to read the tag
547  * @param[in] length Number of bytes available in the input stream
548  * @param[out] tag Structure describing the ASN.1 tag
549  * @param[out] value Integer value
550  * @return Error code
551  **/
552 
553 error_t asn1ReadMpi(const uint8_t *data, size_t length, Asn1Tag *tag,
554  Mpi *value)
555 {
556  error_t error;
557 
558  //Read ASN.1 tag
559  error = asn1ReadTag(data, length, tag);
560  //Failed to decode ASN.1 tag?
561  if(error)
562  return error;
563 
564  //Enforce encoding, class and type
566  //Invalid tag?
567  if(error)
568  return error;
569 
570  //Negative integer?
571  if(tag->length > 0 && (tag->value[0] & 0x80) != 0)
572  return ERROR_INVALID_SYNTAX;
573 
574  //Convert the octet string to a multiple precision integer
575  error = mpiImport(value, tag->value, tag->length, MPI_FORMAT_BIG_ENDIAN);
576 
577  //Return status code
578  return error;
579 }
580 
581 
582 /**
583  * @brief Write a multiple-precision integer from the output stream
584  * @param[in] value Integer value
585  * @param[in] reverse Use reverse encoding
586  * @param[out] data Output stream where to write the tag (optional parameter)
587  * @param[out] written Number of bytes written to the output stream
588  * @return Error code
589  **/
590 
591 error_t asn1WriteMpi(const Mpi *value, bool_t reverse, uint8_t *data,
592  size_t *written)
593 {
594  error_t error;
595  size_t n;
596  Asn1Tag tag;
597 
598  //Retrieve the length of the multiple precision integer
600 
601  //An integer value is always encoded in the smallest possible number of
602  //octets
603  n = (n / 8) + 1;
604 
605  //Valid output stream?
606  if(data != NULL)
607  {
608  //Use reverse encoding?
609  if(reverse)
610  data -= n;
611 
612  //The value of the multiple precision integer is encoded MSB first
614  //Any error to report?
615  if(error)
616  return error;
617  }
618 
619  //The integer is encapsulated within an ASN.1 structure
620  tag.constructed = FALSE;
623  tag.length = n;
624  tag.value = data;
625 
626  //Compute the length of the corresponding ASN.1 structure
627  error = asn1WriteTag(&tag, FALSE, data, NULL);
628  //Any error to report?
629  if(error)
630  return error;
631 
632  //Number of bytes written to the output stream
633  if(written != NULL)
634  *written = tag.totalLength;
635 
636  //Successful processing
637  return NO_ERROR;
638 }
639 
640 #endif
641 
642 
643 /**
644  * @brief Enforce the type of a specified tag
645  * @param[in] tag Pointer to an ASN.1 tag
646  * @param[in] constructed Expected encoding (TRUE for constructed, FALSE
647  * for primitive)
648  * @param[in] objClass Expected tag class
649  * @param[in] objType Expected tag type
650  * @return Error code
651  **/
652 
653 error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass,
654  uint_t objType)
655 {
656  //Check encoding
657  if(tag->constructed != constructed)
658  return ERROR_WRONG_ENCODING;
659  //Enforce class
660  if(tag->objClass != objClass)
661  return ERROR_INVALID_CLASS;
662  //Enforce type
663  if(tag->objType != objType)
664  return ERROR_INVALID_TYPE;
665 
666  //The tag matches all the criteria
667  return NO_ERROR;
668 }
669 
670 
671 /**
672  * @brief Check ASN.1 tag against a specified OID
673  * @param[in] tag Pointer to an ASN.1 tag
674  * @param[in] oid Expected object identifier (OID)
675  * @param[in] length Length of the OID
676  * @return Error code
677  **/
678 
679 error_t asn1CheckOid(const Asn1Tag *tag, const uint8_t *oid, size_t length)
680 {
681  error_t error;
682 
683  //Enforce encoding, class and type
685  //Any error to report?
686  if(error)
687  return error;
688 
689  //Compare OID against the specified value
690  if(oidComp(tag->value, tag->length, oid, length))
691  return ERROR_WRONG_IDENTIFIER;
692 
693  //The tag matches all the criteria
694  return NO_ERROR;
695 }
696 
697 
698 /**
699  * @brief Display an ASN.1 data object
700  * @param[in] data Pointer to the ASN.1 object to dump
701  * @param[in] length Length of the ASN.1 object
702  * @param[in] level Current level of recursion (this parameter shall be set to 0)
703  * @return Error code
704  **/
705 
706 error_t asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
707 {
708 //Check debugging level
709 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
710  error_t error;
711  uint_t i;
712  Asn1Tag tag;
713 
714  //ASN.1 universal types
715  static const char_t *const label[32] =
716  {
717  "[0]",
718  "BOOLEAN",
719  "INTEGER",
720  "BIT STRING",
721  "OCTET STRING",
722  "NULL",
723  "OBJECT IDENTIFIER",
724  "OBJECT DESCRIPTOR",
725  "EXTERNAL",
726  "REAL",
727  "ENUMERATED",
728  "[11]",
729  "UTF8 STRING",
730  "[13]",
731  "[14]",
732  "[15]",
733  "SEQUENCE",
734  "SET",
735  "NUMERIC STRING",
736  "PRINTABLE STRING",
737  "TELETEX STRING",
738  "VIDEOTEX STRING",
739  "IA5 STRING",
740  "UTC TIME",
741  "GENERALIZED TIME",
742  "GRAPHIC STRING",
743  "VISIBLE STRING",
744  "GENERAL STRING",
745  "UNIVERSAL STRING",
746  "[29]",
747  "BMP STRING",
748  "[31]"
749  };
750 
751  //Prefix used to format the structure
752  static const char_t *const prefix[10] =
753  {
754  "",
755  " ",
756  " ",
757  " ",
758  " ",
759  " ",
760  " ",
761  " ",
762  " ",
763  " "
764  };
765 
766  //Parse ASN.1 object
767  while(length > 0)
768  {
769  //Decode current ASN.1 tag
770  error = asn1ReadTag(data, length, &tag);
771  //Decoding failed?
772  if(error)
773  return error;
774 
775  //Point to the next field
776  data += tag.totalLength;
777  length -= tag.totalLength;
778 
779  //Dump tag number, tag class, and contents length fields
780  if(tag.objType < 32 && (tag.objClass & ASN1_CLASS_MASK) == ASN1_CLASS_UNIVERSAL)
781  {
782  TRACE_DEBUG("%s%s (%" PRIuSIZE " bytes)\r\n", prefix[level], label[tag.objType], tag.length);
783  }
784  else
785  {
786  TRACE_DEBUG("%s[%u] (%" PRIuSIZE " bytes)\r\n", prefix[level], tag.objType, tag.length);
787  }
788 
789  //Constructed type?
790  if(tag.constructed)
791  {
792  //Check whether the maximum level of recursion is reached
793  if(level < 8)
794  {
795  //Recursive decoding of the ASN.1 tag
796  error = asn1DumpObject(tag.value, tag.length, level + 1);
797  //Decoding failed?
798  if(error)
799  return error;
800  }
801  else
802  {
803  //If the maximum level of recursion is reached, then dump contents
804  TRACE_DEBUG_ARRAY(prefix[level + 1], tag.value, tag.length);
805  }
806  }
807  else
808  {
809  //Universal tag?
811  {
812  //Check the type of the current tag
813  switch(tag.objType)
814  {
815  //OID?
817  //Append prefix
818  TRACE_DEBUG("%s", prefix[level + 1]);
819  //Print OID
820  TRACE_DEBUG("%s", oidToString(tag.value, tag.length, NULL, 0));
821  //Add a line feed
822  TRACE_DEBUG("\r\n");
823  break;
824 
825  //String?
837  //Append prefix
838  TRACE_DEBUG("%s", prefix[level + 1]);
839 
840  //Dump the entire string
841  for(i = 0; i < tag.length; i++)
842  {
843  TRACE_DEBUG("%c", tag.value[i]);
844  }
845 
846  //Add a line feed
847  TRACE_DEBUG("\r\n");
848  break;
849 
850  //UTC time?
851  case ASN1_TYPE_UTC_TIME:
852  //Check length
853  if(tag.length != 13)
854  return ERROR_WRONG_ENCODING;
855  //The encoding shall terminate with a "Z"
856  if(tag.value[tag.length - 1] != 'Z')
857  return ERROR_WRONG_ENCODING;
858 
859  //Append prefix
860  TRACE_DEBUG("%s", prefix[level + 1]);
861  //Display date
862  TRACE_DEBUG("%c%c/%c%c/%c%c ", tag.value[0], tag.value[1],
863  tag.value[2], tag.value[3], tag.value[4], tag.value[5]);
864  //Display time
865  TRACE_DEBUG("%c%c:%c%c:%c%c", tag.value[6], tag.value[7],
866  tag.value[8], tag.value[9], tag.value[10], tag.value[11]);
867  //Add a line feed
868  TRACE_DEBUG("\r\n");
869  break;
870 
871  //Generalized time?
873  //Check length
874  if(tag.length != 15)
875  return ERROR_WRONG_ENCODING;
876  //The encoding shall terminate with a "Z"
877  if(tag.value[tag.length - 1] != 'Z')
878  return ERROR_WRONG_ENCODING;
879 
880  //Append prefix
881  TRACE_DEBUG("%s", prefix[level + 1]);
882  //Display date
883  TRACE_DEBUG("%c%c%c%c/%c%c/%c%c ", tag.value[0], tag.value[1], tag.value[2],
884  tag.value[3], tag.value[4], tag.value[5], tag.value[6], tag.value[7]);
885  //Display time
886  TRACE_DEBUG("%c%c:%c%c:%c%c", tag.value[8], tag.value[9],
887  tag.value[10], tag.value[11], tag.value[12], tag.value[13]);
888  //Add a line feed
889  TRACE_DEBUG("\r\n");
890  break;
891 
892  //Any other type?
893  default:
894  //Dump the contents of the tag
895  TRACE_DEBUG_ARRAY(prefix[level + 1], tag.value, tag.length);
896  break;
897  }
898  }
899  else
900  {
901  //Dump the contents of the tag
902  TRACE_DEBUG_ARRAY(prefix[level + 1], tag.value, tag.length);
903  }
904  }
905  }
906 #endif
907 
908  //ASN.1 object successfully decoded
909  return NO_ERROR;
910 }
911 
912 #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 asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data, size_t *written)
Write a 32-bit integer to the output stream.
Definition: asn1.c:495
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 asn1WriteMpi(const Mpi *value, bool_t reverse, uint8_t *data, size_t *written)
Write a multiple-precision integer from the output stream.
Definition: asn1.c:591
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:334
error_t asn1CheckOid(const Asn1Tag *tag, const uint8_t *oid, size_t length)
Check ASN.1 tag against a specified OID.
Definition: asn1.c:679
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 asn1ReadBoolean(const uint8_t *data, size_t length, Asn1Tag *tag, bool_t *value)
Read a boolean from the input stream.
Definition: asn1.c:247
error_t asn1ReadMpi(const uint8_t *data, size_t length, Asn1Tag *tag, Mpi *value)
Read a multiple-precision integer from the input stream.
Definition: asn1.c:553
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_GENERAL_STRING
Definition: asn1.h:91
@ ASN1_TYPE_VISIBLE_STRING
Definition: asn1.h:90
@ ASN1_TYPE_BMP_STRING
Definition: asn1.h:93
@ ASN1_TYPE_GENERALIZED_TIME
Definition: asn1.h:88
@ ASN1_TYPE_VIDEOTEX_STRING
Definition: asn1.h:85
@ ASN1_TYPE_OBJECT_IDENTIFIER
Definition: asn1.h:74
@ ASN1_TYPE_NUMERIC_STRING
Definition: asn1.h:82
@ ASN1_TYPE_BOOLEAN
Definition: asn1.h:69
@ ASN1_TYPE_UNIVERSAL_STRING
Definition: asn1.h:92
@ ASN1_TYPE_UTC_TIME
Definition: asn1.h:87
@ ASN1_TYPE_PRINTABLE_STRING
Definition: asn1.h:83
@ ASN1_TYPE_TELETEX_STRING
Definition: asn1.h:84
@ ASN1_TYPE_OCTET_STRING
Definition: asn1.h:72
@ ASN1_TYPE_IA5_STRING
Definition: asn1.h:86
@ ASN1_TYPE_UTF8_STRING
Definition: asn1.h:79
@ ASN1_TYPE_INTEGER
Definition: asn1.h:70
@ ASN1_TYPE_SEQUENCE
Definition: asn1.h:80
@ ASN1_TYPE_GRAPHIC_STRING
Definition: asn1.h:89
#define ASN1_ENCODING_CONSTRUCTED
Definition: asn1.h:48
#define ASN1_CLASS_MASK
Definition: asn1.h:51
#define ASN1_TAG_NUMBER_MASK
Definition: asn1.h:43
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:52
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
General definitions for cryptographic algorithms.
Debugging facilities.
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint8_t n
Ipv6Addr prefix
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ ERROR_INVALID_CLASS
Definition: error.h:117
@ ERROR_WRONG_ENCODING
Definition: error.h:122
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_TAG
Definition: error.h:114
uint8_t data[]
Definition: ethernet.h:222
uint8_t oid[]
Definition: lldp_tlv.h:300
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:234
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:624
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:709
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
uint8_t m
Definition: ndp.h:304
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
char_t * oidToString(const uint8_t *oid, size_t oidLen, char_t *str, size_t maxStrLen)
Convert a binary OID to a string representation.
Definition: oid.c:659
OID (Object Identifier)
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#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
Arbitrary precision integer.
Definition: mpi.h:80
uint8_t length
Definition: tcp.h:368
uint8_t value[]
Definition: tcp.h:369