You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. FILE_LICENCE ( GPL2_OR_LATER );
  19. #include <stdint.h>
  20. #include <stddef.h>
  21. #include <errno.h>
  22. #include <gpxe/asn1.h>
  23. /** @file
  24. *
  25. * ASN.1 encoding
  26. *
  27. */
  28. /**
  29. * Start parsing ASN.1 object
  30. *
  31. * @v cursor ASN.1 object cursor
  32. * @v type Expected type
  33. * @ret len Length of object body, or negative error
  34. *
  35. * The object cursor will be updated to point to the start of the
  36. * object body (i.e. the first byte following the length byte(s)), and
  37. * the length of the object body (i.e. the number of bytes until the
  38. * following object tag, if any) is returned.
  39. *
  40. * If any error occurs (i.e. if the object is not of the expected
  41. * type, or if we overflow beyond the end of the ASN.1 object), then
  42. * the cursor will be invalidated and a negative value will be
  43. * returned.
  44. */
  45. static int asn1_start ( struct asn1_cursor *cursor,
  46. unsigned int type ) {
  47. unsigned int len_len;
  48. unsigned int len;
  49. int rc;
  50. /* Sanity check */
  51. if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
  52. if ( cursor->len )
  53. DBGC ( cursor, "ASN1 %p too short\n", cursor );
  54. rc = -EINVAL;
  55. goto notfound;
  56. }
  57. /* Check the tag byte */
  58. if ( *( ( uint8_t * ) cursor->data ) != type ) {
  59. DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
  60. cursor, type, *( ( uint8_t * ) cursor->data ) );
  61. rc = -ENXIO;
  62. goto notfound;
  63. }
  64. cursor->data++;
  65. cursor->len--;
  66. /* Extract length of the length field and sanity check */
  67. len_len = *( ( uint8_t * ) cursor->data );
  68. if ( len_len & 0x80 ) {
  69. len_len = ( len_len & 0x7f );
  70. cursor->data++;
  71. cursor->len--;
  72. } else {
  73. len_len = 1;
  74. }
  75. if ( cursor->len < len_len ) {
  76. DBGC ( cursor, "ASN1 %p bad length field length %d (max "
  77. "%zd)\n", cursor, len_len, cursor->len );
  78. rc = -EINVAL;
  79. goto notfound;
  80. }
  81. /* Extract the length and sanity check */
  82. for ( len = 0 ; len_len ; len_len-- ) {
  83. len <<= 8;
  84. len |= *( ( uint8_t * ) cursor->data );
  85. cursor->data++;
  86. cursor->len--;
  87. }
  88. if ( cursor->len < len ) {
  89. DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
  90. cursor, len, cursor->len );
  91. rc = -EINVAL;
  92. goto notfound;
  93. }
  94. return len;
  95. notfound:
  96. cursor->data = NULL;
  97. cursor->len = 0;
  98. return rc;
  99. }
  100. /**
  101. * Enter ASN.1 object
  102. *
  103. * @v cursor ASN.1 object cursor
  104. * @v type Expected type
  105. * @ret rc Return status code
  106. *
  107. * The object cursor will be updated to point to the body of the
  108. * current ASN.1 object. If any error occurs, the object cursor will
  109. * be invalidated.
  110. */
  111. int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
  112. int len;
  113. len = asn1_start ( cursor, type );
  114. if ( len < 0 )
  115. return len;
  116. cursor->len = len;
  117. DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
  118. cursor, type, len );
  119. return 0;
  120. }
  121. /**
  122. * Skip ASN.1 object
  123. *
  124. * @v cursor ASN.1 object cursor
  125. * @v type Expected type
  126. * @ret rc Return status code
  127. *
  128. * The object cursor will be updated to point to the next ASN.1
  129. * object. If any error occurs, the object cursor will be
  130. * invalidated.
  131. */
  132. int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
  133. int len;
  134. len = asn1_start ( cursor, type );
  135. if ( len < 0 )
  136. return len;
  137. cursor->data += len;
  138. cursor->len -= len;
  139. DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
  140. cursor, type, len );
  141. if ( ! cursor->len ) {
  142. DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
  143. cursor->data = NULL;
  144. return -ENOENT;
  145. }
  146. return 0;
  147. }