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 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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 <string.h>
  22. #include <errno.h>
  23. #include <ipxe/asn1.h>
  24. /** @file
  25. *
  26. * ASN.1 encoding
  27. *
  28. */
  29. /* Disambiguate the various error causes */
  30. #define EINVAL_ASN1_EMPTY \
  31. __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
  32. #define EINFO_EINVAL_ASN1_EMPTY \
  33. __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
  34. #define EINVAL_ASN1_LEN_LEN \
  35. __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
  36. #define EINFO_EINVAL_ASN1_LEN_LEN \
  37. __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
  38. #define EINVAL_ASN1_LEN \
  39. __einfo_error ( EINFO_EINVAL_ASN1_LEN )
  40. #define EINFO_EINVAL_ASN1_LEN \
  41. __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
  42. #define EINVAL_ASN1_BOOLEAN \
  43. __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
  44. #define EINFO_EINVAL_ASN1_BOOLEAN \
  45. __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
  46. #define EINVAL_ASN1_INTEGER \
  47. __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
  48. #define EINFO_EINVAL_ASN1_INTEGER \
  49. __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
  50. /**
  51. * Invalidate ASN.1 object cursor
  52. *
  53. * @v cursor ASN.1 object cursor
  54. */
  55. void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
  56. static uint8_t asn1_invalid_object[] = { ASN1_END, 0 };
  57. cursor->data = asn1_invalid_object;
  58. cursor->len = 0;
  59. }
  60. /**
  61. * Start parsing ASN.1 object
  62. *
  63. * @v cursor ASN.1 object cursor
  64. * @v type Expected type, or ASN1_ANY
  65. * @ret len Length of object body, or negative error
  66. *
  67. * The object cursor will be updated to point to the start of the
  68. * object body (i.e. the first byte following the length byte(s)), and
  69. * the length of the object body (i.e. the number of bytes until the
  70. * following object tag, if any) is returned.
  71. */
  72. static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
  73. unsigned int len_len;
  74. unsigned int len;
  75. /* Sanity check */
  76. if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
  77. if ( cursor->len )
  78. DBGC ( cursor, "ASN1 %p too short\n", cursor );
  79. return -EINVAL_ASN1_EMPTY;
  80. }
  81. /* Check the tag byte */
  82. if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) {
  83. DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
  84. cursor, type, *( ( uint8_t * ) cursor->data ) );
  85. return -ENXIO;
  86. }
  87. cursor->data++;
  88. cursor->len--;
  89. /* Extract length of the length field and sanity check */
  90. len_len = *( ( uint8_t * ) cursor->data );
  91. if ( len_len & 0x80 ) {
  92. len_len = ( len_len & 0x7f );
  93. cursor->data++;
  94. cursor->len--;
  95. } else {
  96. len_len = 1;
  97. }
  98. if ( cursor->len < len_len ) {
  99. DBGC ( cursor, "ASN1 %p bad length field length %d (max "
  100. "%zd)\n", cursor, len_len, cursor->len );
  101. return -EINVAL_ASN1_LEN_LEN;
  102. }
  103. /* Extract the length and sanity check */
  104. for ( len = 0 ; len_len ; len_len-- ) {
  105. len <<= 8;
  106. len |= *( ( uint8_t * ) cursor->data );
  107. cursor->data++;
  108. cursor->len--;
  109. }
  110. if ( cursor->len < len ) {
  111. DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
  112. cursor, len, cursor->len );
  113. return -EINVAL_ASN1_LEN;
  114. }
  115. return len;
  116. }
  117. /**
  118. * Enter ASN.1 object
  119. *
  120. * @v cursor ASN.1 object cursor
  121. * @v type Expected type, or ASN1_ANY
  122. * @ret rc Return status code
  123. *
  124. * The object cursor will be updated to point to the body of the
  125. * current ASN.1 object. If any error occurs, the object cursor will
  126. * be invalidated.
  127. */
  128. int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
  129. int len;
  130. len = asn1_start ( cursor, type );
  131. if ( len < 0 ) {
  132. asn1_invalidate_cursor ( cursor );
  133. return len;
  134. }
  135. cursor->len = len;
  136. DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
  137. cursor, type, len );
  138. return 0;
  139. }
  140. /**
  141. * Skip ASN.1 object if present
  142. *
  143. * @v cursor ASN.1 object cursor
  144. * @v type Expected type, or ASN1_ANY
  145. * @ret rc Return status code
  146. *
  147. * The object cursor will be updated to point to the next ASN.1
  148. * object. If any error occurs, the object cursor will not be
  149. * modified.
  150. */
  151. int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
  152. int len;
  153. len = asn1_start ( cursor, type );
  154. if ( len < 0 )
  155. return len;
  156. cursor->data += len;
  157. cursor->len -= len;
  158. DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
  159. cursor, type, len );
  160. if ( ! cursor->len ) {
  161. DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
  162. return -ENOENT;
  163. }
  164. return 0;
  165. }
  166. /**
  167. * Skip ASN.1 object
  168. *
  169. * @v cursor ASN.1 object cursor
  170. * @v type Expected type, or ASN1_ANY
  171. * @ret rc Return status code
  172. *
  173. * The object cursor will be updated to point to the next ASN.1
  174. * object. If any error occurs, the object cursor will be
  175. * invalidated.
  176. */
  177. int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
  178. int rc;
  179. if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
  180. asn1_invalidate_cursor ( cursor );
  181. return rc;
  182. }
  183. return 0;
  184. }
  185. /**
  186. * Shrink ASN.1 cursor to fit object
  187. *
  188. * @v cursor ASN.1 object cursor
  189. * @v type Expected type, or ASN1_ANY
  190. * @ret rc Return status code
  191. *
  192. * The object cursor will be shrunk to contain only the current ASN.1
  193. * object. If any error occurs, the object cursor will be
  194. * invalidated.
  195. */
  196. int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
  197. struct asn1_cursor next;
  198. int rc;
  199. /* Skip to next object */
  200. memcpy ( &next, cursor, sizeof ( next ) );
  201. if ( ( rc = asn1_skip ( &next, type ) ) != 0 )
  202. return rc;
  203. /* Shrink original cursor to contain only its first object */
  204. cursor->len = ( next.data - cursor->data );
  205. return 0;
  206. }
  207. /**
  208. * Enter ASN.1 object of any type
  209. *
  210. * @v cursor ASN.1 object cursor
  211. * @ret rc Return status code
  212. */
  213. int asn1_enter_any ( struct asn1_cursor *cursor ) {
  214. return asn1_enter ( cursor, ASN1_ANY );
  215. }
  216. /**
  217. * Skip ASN.1 object of any type
  218. *
  219. * @v cursor ASN.1 object cursor
  220. * @ret rc Return status code
  221. */
  222. int asn1_skip_any ( struct asn1_cursor *cursor ) {
  223. return asn1_skip ( cursor, ASN1_ANY );
  224. }
  225. /**
  226. * Shrink ASN.1 object of any type
  227. *
  228. * @v cursor ASN.1 object cursor
  229. * @ret rc Return status code
  230. */
  231. int asn1_shrink_any ( struct asn1_cursor *cursor ) {
  232. return asn1_shrink ( cursor, ASN1_ANY );
  233. }
  234. /**
  235. * Parse value of ASN.1 boolean
  236. *
  237. * @v cursor ASN.1 object cursor
  238. * @ret value Value, or negative error
  239. */
  240. int asn1_boolean ( const struct asn1_cursor *cursor ) {
  241. struct asn1_cursor contents;
  242. const struct asn1_boolean *boolean;
  243. /* Enter boolean */
  244. memcpy ( &contents, cursor, sizeof ( contents ) );
  245. asn1_enter ( &contents, ASN1_BOOLEAN );
  246. if ( contents.len != sizeof ( *boolean ) )
  247. return -EINVAL_ASN1_BOOLEAN;
  248. /* Extract value */
  249. boolean = contents.data;
  250. return boolean->value;
  251. }
  252. /**
  253. * Parse value of ASN.1 integer
  254. *
  255. * @v cursor ASN.1 object cursor
  256. * @v value Value to fill in
  257. * @ret rc Return status code
  258. */
  259. int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
  260. struct asn1_cursor contents;
  261. uint8_t high_byte;
  262. int rc;
  263. /* Enter integer */
  264. memcpy ( &contents, cursor, sizeof ( contents ) );
  265. if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
  266. return rc;
  267. if ( contents.len < 1 )
  268. return -EINVAL_ASN1_INTEGER;
  269. /* Initialise value according to sign byte */
  270. *value = *( ( int8_t * ) contents.data );
  271. contents.data++;
  272. contents.len--;
  273. /* Process value */
  274. while ( contents.len ) {
  275. high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
  276. if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
  277. DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
  278. return -EINVAL_ASN1_INTEGER;
  279. }
  280. *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
  281. contents.data++;
  282. contents.len--;
  283. }
  284. return 0;
  285. }
  286. /**
  287. * Compare two ASN.1 objects
  288. *
  289. * @v cursor1 ASN.1 object cursor
  290. * @v cursor2 ASN.1 object cursor
  291. * @ret difference Difference as returned by memcmp()
  292. *
  293. * Note that invalid and empty cursors will compare as equal with each
  294. * other.
  295. */
  296. int asn1_compare ( const struct asn1_cursor *cursor1,
  297. const struct asn1_cursor *cursor2 ) {
  298. int difference;
  299. difference = ( cursor2->len - cursor1->len );
  300. return ( difference ? difference :
  301. memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
  302. }