Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

497 wiersze
12 KiB

  1. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  2. * All rights reserved.
  3. *
  4. * This package is an SSL implementation written
  5. * by Eric Young (eay@cryptsoft.com).
  6. * The implementation was written so as to conform with Netscapes SSL.
  7. *
  8. * This library is free for commercial and non-commercial use as long as
  9. * the following conditions are aheared to. The following conditions
  10. * apply to all code found in this distribution, be it the RC4, RSA,
  11. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  12. * included with this distribution is covered by the same copyright terms
  13. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  14. *
  15. * Copyright remains Eric Young's, and as such any Copyright notices in
  16. * the code are not to be removed.
  17. * If this package is used in a product, Eric Young should be given attribution
  18. * as the author of the parts of the library used.
  19. * This can be in the form of a textual message at program startup or
  20. * in documentation (online or textual) provided with the package.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * "This product includes cryptographic software written by
  33. * Eric Young (eay@cryptsoft.com)"
  34. * The word 'cryptographic' can be left out if the rouines from the library
  35. * being used are not cryptographic related :-).
  36. * 4. If you include any Windows specific code (or a derivative thereof) from
  37. * the apps directory (application code) you must include an acknowledgement:
  38. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. *
  52. * The licence and distribution terms for any publically available version or
  53. * derivative of this code cannot be changed. i.e. this code cannot simply be
  54. * copied and put under another distribution licence
  55. * [including the GNU Public Licence.] */
  56. #include <openssl/asn1.h>
  57. #include <assert.h>
  58. #include <string.h>
  59. #include <openssl/bio.h>
  60. #include <openssl/mem.h>
  61. /* Must be large enough for biggest tag+length */
  62. #define DEFAULT_ASN1_BUF_SIZE 20
  63. typedef enum
  64. {
  65. ASN1_STATE_START,
  66. ASN1_STATE_PRE_COPY,
  67. ASN1_STATE_HEADER,
  68. ASN1_STATE_HEADER_COPY,
  69. ASN1_STATE_DATA_COPY,
  70. ASN1_STATE_POST_COPY,
  71. ASN1_STATE_DONE
  72. } asn1_bio_state_t;
  73. typedef struct BIO_ASN1_EX_FUNCS_st
  74. {
  75. asn1_ps_func *ex_func;
  76. asn1_ps_func *ex_free_func;
  77. } BIO_ASN1_EX_FUNCS;
  78. typedef struct BIO_ASN1_BUF_CTX_t
  79. {
  80. /* Internal state */
  81. asn1_bio_state_t state;
  82. /* Internal buffer */
  83. unsigned char *buf;
  84. /* Size of buffer */
  85. int bufsize;
  86. /* Current position in buffer */
  87. int bufpos;
  88. /* Current buffer length */
  89. int buflen;
  90. /* Amount of data to copy */
  91. int copylen;
  92. /* Class and tag to use */
  93. int asn1_class, asn1_tag;
  94. asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
  95. /* Extra buffer for prefix and suffix data */
  96. unsigned char *ex_buf;
  97. int ex_len;
  98. int ex_pos;
  99. void *ex_arg;
  100. } BIO_ASN1_BUF_CTX;
  101. static int asn1_bio_write(BIO *h, const char *buf,int num);
  102. static int asn1_bio_read(BIO *h, char *buf, int size);
  103. static int asn1_bio_puts(BIO *h, const char *str);
  104. static int asn1_bio_gets(BIO *h, char *str, int size);
  105. static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
  106. static int asn1_bio_new(BIO *h);
  107. static int asn1_bio_free(BIO *data);
  108. static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
  109. static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
  110. static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  111. asn1_ps_func *cleanup, asn1_bio_state_t next);
  112. static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  113. asn1_ps_func *setup,
  114. asn1_bio_state_t ex_state,
  115. asn1_bio_state_t other_state);
  116. static const BIO_METHOD methods_asn1=
  117. {
  118. BIO_TYPE_ASN1,
  119. "asn1",
  120. asn1_bio_write,
  121. asn1_bio_read,
  122. asn1_bio_puts,
  123. asn1_bio_gets,
  124. asn1_bio_ctrl,
  125. asn1_bio_new,
  126. asn1_bio_free,
  127. asn1_bio_callback_ctrl,
  128. };
  129. const BIO_METHOD *BIO_f_asn1(void)
  130. {
  131. return(&methods_asn1);
  132. }
  133. static int asn1_bio_new(BIO *b)
  134. {
  135. BIO_ASN1_BUF_CTX *ctx;
  136. ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
  137. if (!ctx)
  138. return 0;
  139. if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
  140. {
  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)
  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;
  169. ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
  170. if (ctx == NULL)
  171. return 0;
  172. if (ctx->buf)
  173. OPENSSL_free(ctx->buf);
  174. OPENSSL_free(ctx);
  175. b->init = 0;
  176. b->ptr = NULL;
  177. b->flags = 0;
  178. return 1;
  179. }
  180. static int asn1_bio_write(BIO *b, const char *in , int inl)
  181. {
  182. BIO_ASN1_BUF_CTX *ctx;
  183. int wrmax, wrlen, ret;
  184. unsigned char *p;
  185. if (!in || (inl < 0) || (b->next_bio == NULL))
  186. return 0;
  187. ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
  188. if (ctx == NULL)
  189. return 0;
  190. wrlen = 0;
  191. ret = -1;
  192. for(;;)
  193. {
  194. switch (ctx->state)
  195. {
  196. /* Setup prefix data, call it */
  197. case ASN1_STATE_START:
  198. if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
  199. ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
  200. return 0;
  201. break;
  202. /* Copy any pre data first */
  203. case ASN1_STATE_PRE_COPY:
  204. ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
  205. ASN1_STATE_HEADER);
  206. if (ret <= 0)
  207. goto done;
  208. break;
  209. case ASN1_STATE_HEADER:
  210. ctx->buflen =
  211. ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
  212. assert(ctx->buflen <= ctx->bufsize);
  213. p = ctx->buf;
  214. ASN1_put_object(&p, 0, inl,
  215. ctx->asn1_tag, ctx->asn1_class);
  216. ctx->copylen = inl;
  217. ctx->state = ASN1_STATE_HEADER_COPY;
  218. break;
  219. case ASN1_STATE_HEADER_COPY:
  220. ret = BIO_write(b->next_bio,
  221. ctx->buf + ctx->bufpos, ctx->buflen);
  222. if (ret <= 0)
  223. goto done;
  224. ctx->buflen -= ret;
  225. if (ctx->buflen)
  226. ctx->bufpos += ret;
  227. else
  228. {
  229. ctx->bufpos = 0;
  230. ctx->state = ASN1_STATE_DATA_COPY;
  231. }
  232. break;
  233. case ASN1_STATE_DATA_COPY:
  234. if (inl > ctx->copylen)
  235. wrmax = ctx->copylen;
  236. else
  237. wrmax = inl;
  238. ret = BIO_write(b->next_bio, in, wrmax);
  239. if (ret <= 0)
  240. break;
  241. wrlen += ret;
  242. ctx->copylen -= ret;
  243. in += ret;
  244. inl -= ret;
  245. if (ctx->copylen == 0)
  246. ctx->state = ASN1_STATE_HEADER;
  247. if (inl == 0)
  248. goto done;
  249. break;
  250. default:
  251. BIO_clear_retry_flags(b);
  252. return 0;
  253. }
  254. }
  255. done:
  256. BIO_clear_retry_flags(b);
  257. BIO_copy_next_retry(b);
  258. return (wrlen > 0) ? wrlen : ret;
  259. }
  260. static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  261. asn1_ps_func *cleanup, asn1_bio_state_t next)
  262. {
  263. int ret;
  264. if (ctx->ex_len <= 0)
  265. return 1;
  266. for(;;)
  267. {
  268. ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
  269. ctx->ex_len);
  270. if (ret <= 0)
  271. break;
  272. ctx->ex_len -= ret;
  273. if (ctx->ex_len > 0)
  274. ctx->ex_pos += ret;
  275. else
  276. {
  277. if(cleanup)
  278. cleanup(b, &ctx->ex_buf, &ctx->ex_len,
  279. &ctx->ex_arg);
  280. ctx->state = next;
  281. ctx->ex_pos = 0;
  282. break;
  283. }
  284. }
  285. return ret;
  286. }
  287. static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
  288. asn1_ps_func *setup,
  289. asn1_bio_state_t ex_state,
  290. asn1_bio_state_t other_state)
  291. {
  292. if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
  293. {
  294. BIO_clear_retry_flags(b);
  295. return 0;
  296. }
  297. if (ctx->ex_len > 0)
  298. ctx->state = ex_state;
  299. else
  300. ctx->state = other_state;
  301. return 1;
  302. }
  303. static int asn1_bio_read(BIO *b, char *in , int inl)
  304. {
  305. if (!b->next_bio)
  306. return 0;
  307. return BIO_read(b->next_bio, in , inl);
  308. }
  309. static int asn1_bio_puts(BIO *b, const char *str)
  310. {
  311. return asn1_bio_write(b, str, strlen(str));
  312. }
  313. static int asn1_bio_gets(BIO *b, char *str, int size)
  314. {
  315. if (!b->next_bio)
  316. return 0;
  317. return BIO_gets(b->next_bio, str , size);
  318. }
  319. static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
  320. {
  321. if (b->next_bio == NULL) return(0);
  322. return BIO_callback_ctrl(b->next_bio,cmd,fp);
  323. }
  324. static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
  325. {
  326. BIO_ASN1_BUF_CTX *ctx;
  327. BIO_ASN1_EX_FUNCS *ex_func;
  328. long ret = 1;
  329. ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
  330. if (ctx == NULL)
  331. return 0;
  332. switch(cmd)
  333. {
  334. case BIO_C_SET_PREFIX:
  335. ex_func = arg2;
  336. ctx->prefix = ex_func->ex_func;
  337. ctx->prefix_free = ex_func->ex_free_func;
  338. break;
  339. case BIO_C_GET_PREFIX:
  340. ex_func = arg2;
  341. ex_func->ex_func = ctx->prefix;
  342. ex_func->ex_free_func = ctx->prefix_free;
  343. break;
  344. case BIO_C_SET_SUFFIX:
  345. ex_func = arg2;
  346. ctx->suffix = ex_func->ex_func;
  347. ctx->suffix_free = ex_func->ex_free_func;
  348. break;
  349. case BIO_C_GET_SUFFIX:
  350. ex_func = arg2;
  351. ex_func->ex_func = ctx->suffix;
  352. ex_func->ex_free_func = ctx->suffix_free;
  353. break;
  354. case BIO_C_SET_EX_ARG:
  355. ctx->ex_arg = arg2;
  356. break;
  357. case BIO_C_GET_EX_ARG:
  358. *(void **)arg2 = ctx->ex_arg;
  359. break;
  360. case BIO_CTRL_FLUSH:
  361. if (!b->next_bio)
  362. return 0;
  363. /* Call post function if possible */
  364. if (ctx->state == ASN1_STATE_HEADER)
  365. {
  366. if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
  367. ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
  368. return 0;
  369. }
  370. if (ctx->state == ASN1_STATE_POST_COPY)
  371. {
  372. ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
  373. ASN1_STATE_DONE);
  374. if (ret <= 0)
  375. return ret;
  376. }
  377. if (ctx->state == ASN1_STATE_DONE)
  378. return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
  379. else
  380. {
  381. BIO_clear_retry_flags(b);
  382. return 0;
  383. }
  384. break;
  385. default:
  386. if (!b->next_bio)
  387. return 0;
  388. return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
  389. }
  390. return ret;
  391. }
  392. static int asn1_bio_set_ex(BIO *b, int cmd,
  393. asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
  394. {
  395. BIO_ASN1_EX_FUNCS extmp;
  396. extmp.ex_func = ex_func;
  397. extmp.ex_free_func = ex_free_func;
  398. return BIO_ctrl(b, cmd, 0, &extmp);
  399. }
  400. static int asn1_bio_get_ex(BIO *b, int cmd,
  401. asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
  402. {
  403. BIO_ASN1_EX_FUNCS extmp;
  404. int ret;
  405. ret = BIO_ctrl(b, cmd, 0, &extmp);
  406. if (ret > 0)
  407. {
  408. *ex_func = extmp.ex_func;
  409. *ex_free_func = extmp.ex_free_func;
  410. }
  411. return ret;
  412. }
  413. int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
  414. {
  415. return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
  416. }
  417. int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
  418. {
  419. return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
  420. }
  421. int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
  422. {
  423. return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
  424. }
  425. int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
  426. {
  427. return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
  428. }