Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

asn1.c 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 <ipxe/asn1.h>
  23. /** @file
  24. *
  25. * ASN.1 encoding
  26. *
  27. */
  28. /* Disambiguate the various error causes */
  29. #define EINVAL_ASN1_EMPTY \
  30. __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
  31. #define EINFO_EINVAL_ASN1_EMPTY \
  32. __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
  33. #define EINVAL_ASN1_LEN_LEN \
  34. __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
  35. #define EINFO_EINVAL_ASN1_LEN_LEN \
  36. __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
  37. #define EINVAL_ASN1_LEN \
  38. __einfo_error ( EINFO_EINVAL_ASN1_LEN )
  39. #define EINFO_EINVAL_ASN1_LEN \
  40. __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
  41. /**
  42. * Start parsing ASN.1 object
  43. *
  44. * @v cursor ASN.1 object cursor
  45. * @v type Expected type
  46. * @ret len Length of object body, or negative error
  47. *
  48. * The object cursor will be updated to point to the start of the
  49. * object body (i.e. the first byte following the length byte(s)), and
  50. * the length of the object body (i.e. the number of bytes until the
  51. * following object tag, if any) is returned.
  52. */
  53. static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
  54. unsigned int len_len;
  55. unsigned int len;
  56. /* Sanity check */
  57. if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
  58. if ( cursor->len )
  59. DBGC ( cursor, "ASN1 %p too short\n", cursor );
  60. return -EINVAL_ASN1_EMPTY;
  61. }
  62. /* Check the tag byte */
  63. if ( *( ( uint8_t * ) cursor->data ) != type ) {
  64. DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
  65. cursor, type, *( ( uint8_t * ) cursor->data ) );
  66. return -ENXIO;
  67. }
  68. cursor->data++;
  69. cursor->len--;
  70. /* Extract length of the length field and sanity check */
  71. len_len = *( ( uint8_t * ) cursor->data );
  72. if ( len_len & 0x80 ) {
  73. len_len = ( len_len & 0x7f );
  74. cursor->data++;
  75. cursor->len--;
  76. } else {
  77. len_len = 1;
  78. }
  79. if ( cursor->len < len_len ) {
  80. DBGC ( cursor, "ASN1 %p bad length field length %d (max "
  81. "%zd)\n", cursor, len_len, cursor->len );
  82. return -EINVAL_ASN1_LEN_LEN;
  83. }
  84. /* Extract the length and sanity check */
  85. for ( len = 0 ; len_len ; len_len-- ) {
  86. len <<= 8;
  87. len |= *( ( uint8_t * ) cursor->data );
  88. cursor->data++;
  89. cursor->len--;
  90. }
  91. if ( cursor->len < len ) {
  92. DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
  93. cursor, len, cursor->len );
  94. return -EINVAL_ASN1_LEN;
  95. }
  96. return len;
  97. }
  98. /**
  99. * Enter ASN.1 object
  100. *
  101. * @v cursor ASN.1 object cursor
  102. * @v type Expected type
  103. * @ret rc Return status code
  104. *
  105. * The object cursor will be updated to point to the body of the
  106. * current ASN.1 object. If any error occurs, the object cursor will
  107. * be invalidated.
  108. */
  109. int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
  110. int len;
  111. len = asn1_start ( cursor, type );
  112. if ( len < 0 ) {
  113. asn1_invalidate_cursor ( cursor );
  114. return len;
  115. }
  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 if present
  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 not be
  130. * modified.
  131. */
  132. int asn1_skip_if_exists ( 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. return -ENOENT;
  144. }
  145. return 0;
  146. }
  147. /**
  148. * Skip ASN.1 object
  149. *
  150. * @v cursor ASN.1 object cursor
  151. * @v type Expected type
  152. * @ret rc Return status code
  153. *
  154. * The object cursor will be updated to point to the next ASN.1
  155. * object. If any error occurs, the object cursor will be
  156. * invalidated.
  157. */
  158. int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
  159. int rc;
  160. if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) < 0 ) {
  161. asn1_invalidate_cursor ( cursor );
  162. return rc;
  163. }
  164. return 0;
  165. }