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.

asn1.c 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. #include <stdint.h>
  19. #include <stddef.h>
  20. #include <errno.h>
  21. #include <gpxe/asn1.h>
  22. /** @file
  23. *
  24. * ASN.1 encoding
  25. *
  26. */
  27. /**
  28. * Start parsing ASN.1 object
  29. *
  30. * @v cursor ASN.1 object cursor
  31. * @v type Expected type
  32. * @ret len Length of object body, or negative error
  33. *
  34. * The object cursor will be updated to point to the start of the
  35. * object body (i.e. the first byte following the length byte(s)), and
  36. * the length of the object body (i.e. the number of bytes until the
  37. * following object tag, if any) is returned.
  38. *
  39. * If any error occurs (i.e. if the object is not of the expected
  40. * type, or if we overflow beyond the end of the ASN.1 object), then
  41. * the cursor will be invalidated and a negative value will be
  42. * returned.
  43. */
  44. static int asn1_start ( struct asn1_cursor *cursor,
  45. unsigned int type ) {
  46. unsigned int len_len;
  47. unsigned int len;
  48. int rc;
  49. /* Sanity check */
  50. if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
  51. if ( cursor->len )
  52. DBGC ( cursor, "ASN1 %p too short\n", cursor );
  53. rc = -EINVAL;
  54. goto notfound;
  55. }
  56. /* Check the tag byte */
  57. if ( *( ( uint8_t * ) cursor->data ) != type ) {
  58. DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
  59. cursor, type, *( ( uint8_t * ) cursor->data ) );
  60. rc = -ENXIO;
  61. goto notfound;
  62. }
  63. cursor->data++;
  64. cursor->len--;
  65. /* Extract length of the length field and sanity check */
  66. len_len = *( ( uint8_t * ) cursor->data );
  67. if ( len_len & 0x80 ) {
  68. len_len = ( len_len & 0x7f );
  69. cursor->data++;
  70. cursor->len--;
  71. } else {
  72. len_len = 1;
  73. }
  74. if ( cursor->len < len_len ) {
  75. DBGC ( cursor, "ASN1 %p bad length field length %d (max "
  76. "%zd)\n", cursor, len_len, cursor->len );
  77. rc = -EINVAL;
  78. goto notfound;
  79. }
  80. /* Extract the length and sanity check */
  81. for ( len = 0 ; len_len ; len_len-- ) {
  82. len <<= 8;
  83. len |= *( ( uint8_t * ) cursor->data );
  84. cursor->data++;
  85. cursor->len--;
  86. }
  87. if ( cursor->len < len ) {
  88. DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
  89. cursor, len, cursor->len );
  90. rc = -EINVAL;
  91. goto notfound;
  92. }
  93. return len;
  94. notfound:
  95. cursor->data = NULL;
  96. cursor->len = 0;
  97. return rc;
  98. }
  99. /**
  100. * Enter ASN.1 object
  101. *
  102. * @v cursor ASN.1 object cursor
  103. * @v type Expected type
  104. * @ret rc Return status code
  105. *
  106. * The object cursor will be updated to point to the body of the
  107. * current ASN.1 object. If any error occurs, the object cursor will
  108. * be invalidated.
  109. */
  110. int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
  111. int len;
  112. len = asn1_start ( cursor, type );
  113. if ( len < 0 )
  114. return len;
  115. cursor->len = len;
  116. DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
  117. cursor, type, len );
  118. return 0;
  119. }
  120. /**
  121. * Skip ASN.1 object
  122. *
  123. * @v cursor ASN.1 object cursor
  124. * @v type Expected type
  125. * @ret rc Return status code
  126. *
  127. * The object cursor will be updated to point to the next ASN.1
  128. * object. If any error occurs, the object cursor will be
  129. * invalidated.
  130. */
  131. int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
  132. int len;
  133. len = asn1_start ( cursor, type );
  134. if ( len < 0 )
  135. return len;
  136. cursor->data += len;
  137. cursor->len -= len;
  138. DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
  139. cursor, type, len );
  140. if ( ! cursor->len ) {
  141. DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
  142. cursor->data = NULL;
  143. return -ENOENT;
  144. }
  145. return 0;
  146. }