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

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