bio_asn1.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  3. * project.
  4. */
  5. /* ====================================================================
  6. * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. All advertising materials mentioning features or use of this
  21. * software must display the following acknowledgment:
  22. * "This product includes software developed by the OpenSSL Project
  23. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24. *
  25. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26. * endorse or promote products derived from this software without
  27. * prior written permission. For written permission, please contact
  28. * licensing@OpenSSL.org.
  29. *
  30. * 5. Products derived from this software may not be called "OpenSSL"
  31. * nor may "OpenSSL" appear in their names without prior written
  32. * permission of the OpenSSL Project.
  33. *
  34. * 6. Redistributions of any form whatsoever must retain the following
  35. * acknowledgment:
  36. * "This product includes software developed by the OpenSSL Project
  37. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38. *
  39. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50. * OF THE POSSIBILITY OF SUCH DAMAGE.
  51. * ====================================================================
  52. *
  53. * This product includes cryptographic software written by Eric Young
  54. * (eay@cryptsoft.com). This product includes software written by Tim
  55. * Hudson (tjh@cryptsoft.com).
  56. *
  57. */
  58. /*
  59. * Experimental ASN1 BIO. When written through the data is converted to an
  60. * ASN1 string type: default is OCTET STRING. Additional functions can be
  61. * provided to add prefix and suffix data.
  62. */
  63. #include <string.h>
  64. #include <openssl/bio.h>
  65. #include <openssl/asn1.h>
  66. /* Must be large enough for biggest tag+length */
  67. #define DEFAULT_ASN1_BUF_SIZE 20
  68. typedef enum {
  69. ASN1_STATE_START,
  70. ASN1_STATE_PRE_COPY,
  71. ASN1_STATE_HEADER,
  72. ASN1_STATE_HEADER_COPY,
  73. ASN1_STATE_DATA_COPY,
  74. ASN1_STATE_POST_COPY,
  75. ASN1_STATE_DONE
  76. } asn1_bio_state_t;
  77. typedef struct BIO_ASN1_EX_FUNCS_st {
  78. asn1_ps_func *ex_func;
  79. asn1_ps_func *ex_free_func;
  80. } BIO_ASN1_EX_FUNCS;
  81. typedef struct BIO_ASN1_BUF_CTX_t {
  82. /* Internal state */
  83. asn1_bio_state_t state;
  84. /* Internal buffer */
  85. unsigned char *buf;
  86. /* Size of buffer */
  87. int bufsize;
  88. /* Current position in buffer */
  89. int bufpos;
  90. /* Current buffer length */
  91. int buflen;
  92. /* Amount of data to copy */
  93. int copylen;
  94. /* Class and tag to use */
  95. int asn1_class, asn1_tag;
  96. asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
  97. /* Extra buffer for prefix and suffix data */
  98. unsigned char *ex_buf;
  99. int ex_len;
  100. int ex_pos;
  101. void *ex_arg;
  102. } BIO_ASN1_BUF_CTX;
  103. static int asn1_bio_write(BIO *h, const char *buf, int num);
  104. static int asn1_bio_read(BIO *h, char *buf, int size);
  105. static int asn1_bio_puts(BIO *h, const char *str);
  106. static int asn1_bio_gets(BIO *h, char *str, int size);
  107. static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
  108. static int asn1_bio_new(BIO *h);
  109. static int asn1_bio_free(BIO *data);
  110. static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
  111. static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
  112. static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  113. asn1_ps_func *cleanup, asn1_bio_state_t next);
  114. static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  115. asn1_ps_func *setup,
  116. asn1_bio_state_t ex_state,
  117. asn1_bio_state_t other_state);
  118. static BIO_METHOD methods_asn1 = {
  119. BIO_TYPE_ASN1,
  120. "asn1",
  121. asn1_bio_write,
  122. asn1_bio_read,
  123. asn1_bio_puts,
  124. asn1_bio_gets,
  125. asn1_bio_ctrl,
  126. asn1_bio_new,
  127. asn1_bio_free,
  128. asn1_bio_callback_ctrl,
  129. };
  130. BIO_METHOD *BIO_f_asn1(void)
  131. {
  132. return (&methods_asn1);
  133. }
  134. static int asn1_bio_new(BIO *b)
  135. {
  136. BIO_ASN1_BUF_CTX *ctx;
  137. ctx = OPENSSL_malloc(sizeof(*ctx));
  138. if (ctx == NULL)
  139. return 0;
  140. if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
  141. OPENSSL_free(ctx);
  142. return 0;
  143. }
  144. b->init = 1;
  145. b->ptr = (char *)ctx;
  146. b->flags = 0;
  147. return 1;
  148. }
  149. static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
  150. {
  151. ctx->buf = OPENSSL_malloc(size);
  152. if (ctx->buf == NULL)
  153. return 0;
  154. ctx->bufsize = size;
  155. ctx->bufpos = 0;
  156. ctx->buflen = 0;
  157. ctx->copylen = 0;
  158. ctx->asn1_class = V_ASN1_UNIVERSAL;
  159. ctx->asn1_tag = V_ASN1_OCTET_STRING;
  160. ctx->ex_buf = 0;
  161. ctx->ex_pos = 0;
  162. ctx->ex_len = 0;
  163. ctx->state = ASN1_STATE_START;
  164. return 1;
  165. }
  166. static int asn1_bio_free(BIO *b)
  167. {
  168. BIO_ASN1_BUF_CTX *ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
  169. if (ctx == NULL)
  170. return 0;
  171. OPENSSL_free(ctx->buf);
  172. OPENSSL_free(ctx);
  173. b->init = 0;
  174. b->ptr = NULL;
  175. b->flags = 0;
  176. return 1;
  177. }
  178. static int asn1_bio_write(BIO *b, const char *in, int inl)
  179. {
  180. BIO_ASN1_BUF_CTX *ctx;
  181. int wrmax, wrlen, ret;
  182. unsigned char *p;
  183. if (!in || (inl < 0) || (b->next_bio == NULL))
  184. return 0;
  185. ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
  186. if (ctx == NULL)
  187. return 0;
  188. wrlen = 0;
  189. ret = -1;
  190. for (;;) {
  191. switch (ctx->state) {
  192. /* Setup prefix data, call it */
  193. case ASN1_STATE_START:
  194. if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
  195. ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
  196. return 0;
  197. break;
  198. /* Copy any pre data first */
  199. case ASN1_STATE_PRE_COPY:
  200. ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
  201. ASN1_STATE_HEADER);
  202. if (ret <= 0)
  203. goto done;
  204. break;
  205. case ASN1_STATE_HEADER:
  206. ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
  207. OPENSSL_assert(ctx->buflen <= ctx->bufsize);
  208. p = ctx->buf;
  209. ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
  210. ctx->copylen = inl;
  211. ctx->state = ASN1_STATE_HEADER_COPY;
  212. break;
  213. case ASN1_STATE_HEADER_COPY:
  214. ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
  215. if (ret <= 0)
  216. goto done;
  217. ctx->buflen -= ret;
  218. if (ctx->buflen)
  219. ctx->bufpos += ret;
  220. else {
  221. ctx->bufpos = 0;
  222. ctx->state = ASN1_STATE_DATA_COPY;
  223. }
  224. break;
  225. case ASN1_STATE_DATA_COPY:
  226. if (inl > ctx->copylen)
  227. wrmax = ctx->copylen;
  228. else
  229. wrmax = inl;
  230. ret = BIO_write(b->next_bio, in, wrmax);
  231. if (ret <= 0)
  232. break;
  233. wrlen += ret;
  234. ctx->copylen -= ret;
  235. in += ret;
  236. inl -= ret;
  237. if (ctx->copylen == 0)
  238. ctx->state = ASN1_STATE_HEADER;
  239. if (inl == 0)
  240. goto done;
  241. break;
  242. default:
  243. BIO_clear_retry_flags(b);
  244. return 0;
  245. }
  246. }
  247. done:
  248. BIO_clear_retry_flags(b);
  249. BIO_copy_next_retry(b);
  250. return (wrlen > 0) ? wrlen : ret;
  251. }
  252. static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  253. asn1_ps_func *cleanup, asn1_bio_state_t next)
  254. {
  255. int ret;
  256. if (ctx->ex_len <= 0)
  257. return 1;
  258. for (;;) {
  259. ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
  260. if (ret <= 0)
  261. break;
  262. ctx->ex_len -= ret;
  263. if (ctx->ex_len > 0)
  264. ctx->ex_pos += ret;
  265. else {
  266. if (cleanup)
  267. cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
  268. ctx->state = next;
  269. ctx->ex_pos = 0;
  270. break;
  271. }
  272. }
  273. return ret;
  274. }
  275. static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  276. asn1_ps_func *setup,
  277. asn1_bio_state_t ex_state,
  278. asn1_bio_state_t other_state)
  279. {
  280. if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
  281. BIO_clear_retry_flags(b);
  282. return 0;
  283. }
  284. if (ctx->ex_len > 0)
  285. ctx->state = ex_state;
  286. else
  287. ctx->state = other_state;
  288. return 1;
  289. }
  290. static int asn1_bio_read(BIO *b, char *in, int inl)
  291. {
  292. if (!b->next_bio)
  293. return 0;
  294. return BIO_read(b->next_bio, in, inl);
  295. }
  296. static int asn1_bio_puts(BIO *b, const char *str)
  297. {
  298. return asn1_bio_write(b, str, strlen(str));
  299. }
  300. static int asn1_bio_gets(BIO *b, char *str, int size)
  301. {
  302. if (!b->next_bio)
  303. return 0;
  304. return BIO_gets(b->next_bio, str, size);
  305. }
  306. static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
  307. {
  308. if (b->next_bio == NULL)
  309. return (0);
  310. return BIO_callback_ctrl(b->next_bio, cmd, fp);
  311. }
  312. static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
  313. {
  314. BIO_ASN1_BUF_CTX *ctx;
  315. BIO_ASN1_EX_FUNCS *ex_func;
  316. long ret = 1;
  317. ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
  318. if (ctx == NULL)
  319. return 0;
  320. switch (cmd) {
  321. case BIO_C_SET_PREFIX:
  322. ex_func = arg2;
  323. ctx->prefix = ex_func->ex_func;
  324. ctx->prefix_free = ex_func->ex_free_func;
  325. break;
  326. case BIO_C_GET_PREFIX:
  327. ex_func = arg2;
  328. ex_func->ex_func = ctx->prefix;
  329. ex_func->ex_free_func = ctx->prefix_free;
  330. break;
  331. case BIO_C_SET_SUFFIX:
  332. ex_func = arg2;
  333. ctx->suffix = ex_func->ex_func;
  334. ctx->suffix_free = ex_func->ex_free_func;
  335. break;
  336. case BIO_C_GET_SUFFIX:
  337. ex_func = arg2;
  338. ex_func->ex_func = ctx->suffix;
  339. ex_func->ex_free_func = ctx->suffix_free;
  340. break;
  341. case BIO_C_SET_EX_ARG:
  342. ctx->ex_arg = arg2;
  343. break;
  344. case BIO_C_GET_EX_ARG:
  345. *(void **)arg2 = ctx->ex_arg;
  346. break;
  347. case BIO_CTRL_FLUSH:
  348. if (!b->next_bio)
  349. return 0;
  350. /* Call post function if possible */
  351. if (ctx->state == ASN1_STATE_HEADER) {
  352. if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
  353. ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
  354. return 0;
  355. }
  356. if (ctx->state == ASN1_STATE_POST_COPY) {
  357. ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
  358. ASN1_STATE_DONE);
  359. if (ret <= 0)
  360. return ret;
  361. }
  362. if (ctx->state == ASN1_STATE_DONE)
  363. return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
  364. else {
  365. BIO_clear_retry_flags(b);
  366. return 0;
  367. }
  368. default:
  369. if (!b->next_bio)
  370. return 0;
  371. return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
  372. }
  373. return ret;
  374. }
  375. static int asn1_bio_set_ex(BIO *b, int cmd,
  376. asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
  377. {
  378. BIO_ASN1_EX_FUNCS extmp;
  379. extmp.ex_func = ex_func;
  380. extmp.ex_free_func = ex_free_func;
  381. return BIO_ctrl(b, cmd, 0, &extmp);
  382. }
  383. static int asn1_bio_get_ex(BIO *b, int cmd,
  384. asn1_ps_func **ex_func,
  385. asn1_ps_func **ex_free_func)
  386. {
  387. BIO_ASN1_EX_FUNCS extmp;
  388. int ret;
  389. ret = BIO_ctrl(b, cmd, 0, &extmp);
  390. if (ret > 0) {
  391. *ex_func = extmp.ex_func;
  392. *ex_free_func = extmp.ex_free_func;
  393. }
  394. return ret;
  395. }
  396. int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
  397. asn1_ps_func *prefix_free)
  398. {
  399. return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
  400. }
  401. int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
  402. asn1_ps_func **pprefix_free)
  403. {
  404. return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
  405. }
  406. int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
  407. asn1_ps_func *suffix_free)
  408. {
  409. return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
  410. }
  411. int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
  412. asn1_ps_func **psuffix_free)
  413. {
  414. return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
  415. }