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-2020 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 1.9.8
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 Read a multiple-precision integer from the input stream
327  * @param[in] data Input stream where to read the tag
328  * @param[in] length Number of bytes available in the input stream
329  * @param[out] tag Structure describing the ASN.1 tag
330  * @param[out] value Integer value
331  * @return Error code
332  **/
333 
334 error_t asn1ReadMpi(const uint8_t *data, size_t length, Asn1Tag *tag,
335  Mpi *value)
336 {
337 #if (MPI_SUPPORT == ENABLED)
338  error_t error;
339 
340  //Read ASN.1 tag
341  error = asn1ReadTag(data, length, tag);
342  //Failed to decode ASN.1 tag?
343  if(error)
344  return error;
345 
346  //Enforce encoding, class and type
348  //Invalid tag?
349  if(error)
350  return error;
351 
352  //Negative integer?
353  if(tag->length > 0 && (tag->value[0] & 0x80) != 0)
354  return ERROR_INVALID_SYNTAX;
355 
356  //Convert the octet string to a multiple precision integer
357  error = mpiImport(value, tag->value, tag->length, MPI_FORMAT_BIG_ENDIAN);
358 
359  //Return status code
360  return error;
361 #else
362  //Not implemented
363  return ERROR_NOT_IMPLEMENTED;
364 #endif
365 }
366 
367 
368 /**
369  * @brief Write an ASN.1 tag
370  * @param[in] tag Structure describing the ASN.1 tag
371  * @param[in] reverse Use reverse encoding
372  * @param[out] data Output stream where to write the tag (optional parameter)
373  * @param[out] written Number of bytes written to the output stream (optional parameter)
374  * @return Error code
375  **/
376 
377 error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data,
378  size_t *written)
379 {
380  size_t i;
381  size_t m;
382  size_t n;
383 
384  //Compute the number of octets that are necessary to encode the tag number
385  if(tag->objType < 31)
386  {
387  m = 0;
388  }
389  else if(tag->objType < 128)
390  {
391  m = 1;
392  }
393  else if(tag->objType < 16384)
394  {
395  m = 2;
396  }
397  else if(tag->objType < 2097152)
398  {
399  m = 3;
400  }
401  else if(tag->objType < 268435456)
402  {
403  m = 4;
404  }
405  else
406  {
407  m = 5;
408  }
409 
410  //Compute the number of octets that are necessary to encode the length field
411  if(tag->length < 128)
412  {
413  n = 0;
414  }
415  else if(tag->length < 256)
416  {
417  n = 1;
418  }
419  else if(tag->length < 65536)
420  {
421  n = 2;
422  }
423  else if(tag->length < 16777216)
424  {
425  n = 3;
426  }
427  else
428  {
429  n = 4;
430  }
431 
432  //Valid output stream?
433  if(data != NULL)
434  {
435  //Use reverse encoding?
436  if(reverse)
437  {
438  //Any data to copy?
439  if(tag->value != NULL && tag->length > 0)
440  {
441  //Make room for the data
442  data -= tag->length;
443  //Copy data
444  osMemmove(data, tag->value, tag->length);
445  }
446 
447  //Move backward
448  data -= m + n + 2;
449  }
450  else
451  {
452  //Any data to copy?
453  if(tag->value != NULL && tag->length > 0)
454  {
455  //Copy data
456  osMemmove(data + m + n + 2, tag->value, tag->length);
457  }
458  }
459 
460  //Save the class of the ASN.1 tag
461  data[0] = tag->objClass;
462 
463  //Primitive or constructed encoding?
464  if(tag->constructed)
466 
467  //Encode the tag number
468  if(m == 0)
469  {
470  //Tag number is in the range 0 to 30
471  data[0] |= tag->objType;
472  }
473  else
474  {
475  //The tag number is greater than or equal to 31
477 
478  //The subsequent octets will encode the tag number
479  for(i = 0; i < m; i++)
480  {
481  //Bits 7 to 1 encode the tag number
482  data[m - i] = (tag->objType >> (i * 7)) & 0x7F;
483 
484  //Bit 8 of each octet shall be set to one unless it is the
485  //last octet of the identifier octets
486  if(i != 0)
487  data[m - i] |= 0x80;
488  }
489  }
490 
491  //Encode the length field
492  if(n == 0)
493  {
494  //Use short form encoding
495  data[1 + m] = tag->length & 0x7F;
496  }
497  else
498  {
499  //Bits 7 to 1 encode the number of octets in the length field
500  data[1 + m] = 0x80 | (n & 0x7F);
501 
502  //The subsequent octets will encode the length field
503  for(i = 0; i < n; i++)
504  {
505  data[1 + m + n - i] = (tag->length >> (i * 8)) & 0xFF;
506  }
507  }
508  }
509 
510  //Total length occupied by the ASN.1 tag
511  tag->totalLength = tag->length + m + n + 2;
512 
513  //The last parameter is optional
514  if(written != NULL)
515  {
516  //Number of bytes written to the output stream
517  *written = m + n + 2;
518 
519  //Any data copied?
520  if(tag->value != NULL)
521  *written += tag->length;
522  }
523 
524  //Successful processing
525  return NO_ERROR;
526 }
527 
528 
529 /**
530  * @brief Write a 32-bit integer to the output stream
531  * @param[in] value Integer value
532  * @param[in] reverse Use reverse encoding
533  * @param[out] data Output stream where to write the tag (optional parameter)
534  * @param[out] written Number of bytes written to the output stream
535  * @return Error code
536  **/
537 
538 error_t asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data,
539  size_t *written)
540 {
541  size_t i;
542  size_t n;
543  uint16_t msb;
544 
545  //An integer value is always encoded in the smallest possible number of
546  //octets
547  for(n = 4; n > 1; n--)
548  {
549  //Retrieve the upper 9 bits
550  msb = (value >> (n * 8 - 9)) & 0x01FF;
551 
552  //The upper 9 bits shall not have the same value (all 0 or all 1)
553  if(msb != 0x0000 && msb != 0x01FF)
554  break;
555  }
556 
557  //Valid output stream?
558  if(data != NULL)
559  {
560  //Use reverse encoding?
561  if(reverse)
562  data -= n + 2;
563 
564  //Write tag type
566  //Write tag length
567  data[1] = n & 0xFF;
568 
569  //Write contents octets
570  for(i = 0; i < n; i++)
571  {
572  data[1 + n - i] = (value >> (i * 8)) & 0xFF;
573  }
574  }
575 
576  //Number of bytes written to the output stream
577  if(written != NULL)
578  *written = n + 2;
579 
580  //Successful processing
581  return NO_ERROR;
582 }
583 
584 
585 /**
586  * @brief Write a multiple-precision integer from the output stream
587  * @param[in] value Integer value
588  * @param[in] reverse Use reverse encoding
589  * @param[out] data Output stream where to write the tag (optional parameter)
590  * @param[out] written Number of bytes written to the output stream
591  * @return Error code
592  **/
593 
594 error_t asn1WriteMpi(const Mpi *value, bool_t reverse, uint8_t *data,
595  size_t *written)
596 {
597 #if (MPI_SUPPORT == ENABLED)
598  error_t error;
599  size_t n;
600  Asn1Tag tag;
601 
602  //Retrieve the length of the multiple precision integer
604 
605  //An integer value is always encoded in the smallest possible number of
606  //octets
607  n = (n / 8) + 1;
608 
609  //Valid output stream?
610  if(data != NULL)
611  {
612  //Use reverse encoding?
613  if(reverse)
614  data -= n;
615 
616  //The value of the multiple precision integer is encoded MSB first
618  //Any error to report?
619  if(error)
620  return error;
621  }
622 
623  //The integer is encapsulated within an ASN.1 structure
624  tag.constructed = FALSE;
627  tag.length = n;
628  tag.value = data;
629 
630  //Compute the length of the corresponding ASN.1 structure
631  error = asn1WriteTag(&tag, FALSE, data, NULL);
632  //Any error to report?
633  if(error)
634  return error;
635 
636  //Number of bytes written to the output stream
637  if(written != NULL)
638  *written = tag.totalLength;
639 
640  //Successful processing
641  return NO_ERROR;
642 #else
643  //Not implemented
644  return ERROR_NOT_IMPLEMENTED;
645 #endif
646 }
647 
648 
649 /**
650  * @brief Enforce the type of a specified tag
651  * @param[in] tag Pointer to an ASN.1 tag
652  * @param[in] constructed Expected encoding (TRUE for constructed, FALSE
653  * for primitive)
654  * @param[in] objClass Expected tag class
655  * @param[in] objType Expected tag type
656  * @return Error code
657  **/
658 
659 error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass,
660  uint_t objType)
661 {
662  //Check encoding
663  if(tag->constructed != constructed)
664  return ERROR_WRONG_ENCODING;
665  //Enforce class
666  if(tag->objClass != objClass)
667  return ERROR_INVALID_CLASS;
668  //Enforce type
669  if(tag->objType != objType)
670  return ERROR_INVALID_TYPE;
671 
672  //The tag matches all the criteria
673  return NO_ERROR;
674 }
675 
676 
677 /**
678  * @brief Check ASN.1 tag against a specified OID
679  * @param[in] tag Pointer to an ASN.1 tag
680  * @param[in] oid Expected object identifier (OID)
681  * @param[in] length Length of the OID
682  * @return Error code
683  **/
684 
685 error_t asn1CheckOid(const Asn1Tag *tag, const uint8_t *oid, size_t length)
686 {
687  error_t error;
688 
689  //Enforce encoding, class and type
691  //Any error to report?
692  if(error)
693  return error;
694 
695  //Compare OID against the specified value
696  if(oidComp(tag->value, tag->length, oid, length))
697  return ERROR_WRONG_IDENTIFIER;
698 
699  //The tag matches all the criteria
700  return NO_ERROR;
701 }
702 
703 
704 /**
705  * @brief Display an ASN.1 data object
706  * @param[in] data Pointer to the ASN.1 object to dump
707  * @param[in] length Length of the ASN.1 object
708  * @param[in] level Current level of recursion (this parameter shall be set to 0)
709  * @return Error code
710  **/
711 
712 error_t asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
713 {
714 //Check debugging level
715 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
716  error_t error;
717  uint_t i;
718  Asn1Tag tag;
719 
720  //ASN.1 universal types
721  static const char_t *label[32] =
722  {
723  "[0]",
724  "BOOLEAN",
725  "INTEGER",
726  "BIT STRING",
727  "OCTET STRING",
728  "NULL",
729  "OBJECT IDENTIFIER",
730  "OBJECT DESCRIPTOR",
731  "EXTERNAL",
732  "REAL",
733  "ENUMERATED",
734  "[11]",
735  "UTF8 STRING",
736  "[13]",
737  "[14]",
738  "[15]",
739  "SEQUENCE",
740  "SET",
741  "NUMERIC STRING",
742  "PRINTABLE STRING",
743  "TELETEX STRING",
744  "VIDEOTEX STRING",
745  "IA5 STRING",
746  "UTC TIME",
747  "GENERALIZED TIME",
748  "GRAPHIC STRING",
749  "VISIBLE STRING",
750  "GENERAL STRING",
751  "UNIVERSAL STRING",
752  "[29]",
753  "BMP STRING",
754  "[31]"
755  };
756 
757  //Prefix used to format the structure
758  static const char_t *prefix[10] =
759  {
760  "",
761  " ",
762  " ",
763  " ",
764  " ",
765  " ",
766  " ",
767  " ",
768  " ",
769  " "
770  };
771 
772  //Parse ASN.1 object
773  while(length > 0)
774  {
775  //Decode current ASN.1 tag
776  error = asn1ReadTag(data, length, &tag);
777  //Decoding failed?
778  if(error)
779  return error;
780 
781  //Point to the next field
782  data += tag.totalLength;
783  length -= tag.totalLength;
784 
785  //Dump tag number, tag class, and contents length fields
786  if(tag.objType < 32 && (tag.objClass & ASN1_CLASS_MASK) == ASN1_CLASS_UNIVERSAL)
787  {
788  TRACE_DEBUG("%s%s (%" PRIuSIZE " bytes)\r\n", prefix[level], label[tag.objType], tag.length);
789  }
790  else
791  {
792  TRACE_DEBUG("%s[%u] (%" PRIuSIZE " bytes)\r\n", prefix[level], tag.objType, tag.length);
793  }
794 
795  //Constructed type?
796  if(tag.constructed)
797  {
798  //Check whether the maximum level of recursion is reached
799  if(level < 8)
800  {
801  //Recursive decoding of the ASN.1 tag
802  error = asn1DumpObject(tag.value, tag.length, level + 1);
803  //Decoding failed?
804  if(error)
805  return error;
806  }
807  else
808  {
809  //If the maximum level of recursion is reached, then dump contents
810  TRACE_DEBUG_ARRAY(prefix[level + 1], tag.value, tag.length);
811  }
812  }
813  //Primitive type?
814  else
815  {
816  //Check the type of the current tag
817  switch(tag.objType)
818  {
819  //OID?
821  //Append prefix
822  TRACE_DEBUG(prefix[level + 1]);
823  //Print OID
824  TRACE_DEBUG("%s", oidToString(tag.value, tag.length, NULL, 0));
825  //Add a line feed
826  TRACE_DEBUG("\r\n");
827  break;
828 
829  //String?
841  //Append prefix
842  TRACE_DEBUG("%s", prefix[level + 1]);
843 
844  //Dump the entire string
845  for(i = 0; i < tag.length; i++)
846  {
847  TRACE_DEBUG("%c", tag.value[i]);
848  }
849 
850  //Add a line feed
851  TRACE_DEBUG("\r\n");
852  break;
853 
854  //UTC time?
855  case ASN1_TYPE_UTC_TIME:
856  //Check length
857  if(tag.length != 13)
858  return ERROR_WRONG_ENCODING;
859  //The encoding shall terminate with a "Z"
860  if(tag.value[tag.length - 1] != 'Z')
861  return ERROR_WRONG_ENCODING;
862 
863  //Append prefix
864  TRACE_DEBUG("%s", prefix[level + 1]);
865  //Display date
866  TRACE_DEBUG("%c%c/%c%c/%c%c ", tag.value[0], tag.value[1],
867  tag.value[2], tag.value[3], tag.value[4], tag.value[5]);
868  //Display time
869  TRACE_DEBUG("%c%c:%c%c:%c%c", tag.value[6], tag.value[7],
870  tag.value[8], tag.value[9], tag.value[10], tag.value[11]);
871  //Add a line feed
872  TRACE_DEBUG("\r\n");
873  break;
874 
875  //Generalized time?
877  //Check length
878  if(tag.length != 15)
879  return ERROR_WRONG_ENCODING;
880  //The encoding shall terminate with a "Z"
881  if(tag.value[tag.length - 1] != 'Z')
882  return ERROR_WRONG_ENCODING;
883 
884  //Append prefix
885  TRACE_DEBUG("%s", prefix[level + 1]);
886  //Display date
887  TRACE_DEBUG("%c%c%c%c/%c%c/%c%c ", tag.value[0], tag.value[1], tag.value[2],
888  tag.value[3], tag.value[4], tag.value[5], tag.value[6], tag.value[7]);
889  //Display time
890  TRACE_DEBUG("%c%c:%c%c:%c%c", tag.value[8], tag.value[9],
891  tag.value[10], tag.value[11], tag.value[12], tag.value[13]);
892  //Add a line feed
893  TRACE_DEBUG("\r\n");
894  break;
895 
896  //Any other type?
897  default:
898  //Dump the contents of the tag
899  TRACE_DEBUG_ARRAY(prefix[level + 1], tag.value, tag.length);
900  break;
901  }
902  }
903  }
904 #endif
905 
906  //ASN.1 object successfully decoded
907  return NO_ERROR;
908 }
909 
910 #endif
uint8_t length
Definition: coap_common.h:190
int bool_t
Definition: compiler_port.h:49
uint8_t data[]
Definition: ethernet.h:209
Arbitrary precision integer.
Definition: mpi.h:69
#define ASN1_CLASS_MASK
Definition: asn1.h:47
OID (Object Identifier)
#define TRUE
Definition: os_port.h:50
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 asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
Display an ASN.1 data object.
Definition: asn1.c:712
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 mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:533
Ipv6Addr prefix
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:101
#define ASN1_ENCODING_CONSTRUCTED
Definition: asn1.h:44
error_t asn1ReadOid(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an object identifier from the input stream.
Definition: asn1.c:218
uint8_t level
Definition: tls.h:1725
size_t totalLength
Definition: asn1.h:104
size_t length
Definition: asn1.h:102
#define FALSE
Definition: os_port.h:46
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 mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:618
error_t
Error codes.
Definition: error.h:42
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:48
uint8_t value[]
Definition: tcp.h:332
ASN.1 tag.
Definition: asn1.h:97
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
#define ASN1_TAG_NUMBER_MASK
Definition: asn1.h:39
General definitions for cryptographic algorithms.
uint8_t oid[1]
Definition: mib_common.h:186
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:594
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:377
uint_t objClass
Definition: asn1.h:100
error_t asn1CheckOid(const Asn1Tag *tag, const uint8_t *oid, size_t length)
Check ASN.1 tag against a specified OID.
Definition: asn1.c:685
uint_t mpiGetBitLength(const Mpi *a)
Get the actual length in bits.
Definition: mpi.c:195
#define TRACE_DEBUG(...)
Definition: debug.h:107
char char_t
Definition: compiler_port.h:43
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
uint8_t m
Definition: ndp.h:302
uint8_t n
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:558
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:334
bool_t constructed
Definition: asn1.h:99
#define PRIuSIZE
Definition: compiler_port.h:78
unsigned int uint_t
Definition: compiler_port.h:45
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 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:538
const uint8_t * value
Definition: asn1.h:103
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:659
Success.
Definition: error.h:44
Debugging facilities.
uint_t objType
Definition: asn1.h:101
#define osMemmove(dest, src, length)
Definition: os_port.h:140
ASN.1 (Abstract Syntax Notation One)