A local copy of OpenSSL from GitHub
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.

199 lines
5.1 KiB

  1. /*
  2. * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <openssl/asn1.h>
  10. #include <openssl/asn1t.h>
  11. #include <openssl/bio.h>
  12. #include <openssl/err.h>
  13. #include <stdio.h>
  14. /* Experimental NDEF ASN1 BIO support routines */
  15. /*
  16. * The usage is quite simple, initialize an ASN1 structure, get a BIO from it
  17. * then any data written through the BIO will end up translated to
  18. * appropriate format on the fly. The data is streamed out and does *not*
  19. * need to be all held in memory at once. When the BIO is flushed the output
  20. * is finalized and any signatures etc written out. The BIO is a 'proper'
  21. * BIO and can handle non blocking I/O correctly. The usage is simple. The
  22. * implementation is *not*...
  23. */
  24. /* BIO support data stored in the ASN1 BIO ex_arg */
  25. typedef struct ndef_aux_st {
  26. /* ASN1 structure this BIO refers to */
  27. ASN1_VALUE *val;
  28. const ASN1_ITEM *it;
  29. /* Top of the BIO chain */
  30. BIO *ndef_bio;
  31. /* Output BIO */
  32. BIO *out;
  33. /* Boundary where content is inserted */
  34. unsigned char **boundary;
  35. /* DER buffer start */
  36. unsigned char *derbuf;
  37. } NDEF_SUPPORT;
  38. static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
  39. static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
  40. void *parg);
  41. static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
  42. static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
  43. void *parg);
  44. BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
  45. {
  46. NDEF_SUPPORT *ndef_aux = NULL;
  47. BIO *asn_bio = NULL;
  48. const ASN1_AUX *aux = it->funcs;
  49. ASN1_STREAM_ARG sarg;
  50. if (!aux || !aux->asn1_cb) {
  51. ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
  52. return NULL;
  53. }
  54. ndef_aux = OPENSSL_malloc(sizeof(*ndef_aux));
  55. asn_bio = BIO_new(BIO_f_asn1());
  56. /* ASN1 bio needs to be next to output BIO */
  57. out = BIO_push(asn_bio, out);
  58. if (ndef_aux == NULL || asn_bio == NULL || !out)
  59. goto err;
  60. BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
  61. BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
  62. /*
  63. * Now let callback prepends any digest, cipher etc BIOs ASN1 structure
  64. * needs.
  65. */
  66. sarg.out = out;
  67. sarg.ndef_bio = NULL;
  68. sarg.boundary = NULL;
  69. if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
  70. goto err;
  71. ndef_aux->val = val;
  72. ndef_aux->it = it;
  73. ndef_aux->ndef_bio = sarg.ndef_bio;
  74. ndef_aux->boundary = sarg.boundary;
  75. ndef_aux->out = out;
  76. BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
  77. return sarg.ndef_bio;
  78. err:
  79. BIO_free(asn_bio);
  80. OPENSSL_free(ndef_aux);
  81. return NULL;
  82. }
  83. static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
  84. {
  85. NDEF_SUPPORT *ndef_aux;
  86. unsigned char *p;
  87. int derlen;
  88. if (!parg)
  89. return 0;
  90. ndef_aux = *(NDEF_SUPPORT **)parg;
  91. derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
  92. p = OPENSSL_malloc(derlen);
  93. if (p == NULL)
  94. return 0;
  95. ndef_aux->derbuf = p;
  96. *pbuf = p;
  97. derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
  98. if (!*ndef_aux->boundary)
  99. return 0;
  100. *plen = *ndef_aux->boundary - *pbuf;
  101. return 1;
  102. }
  103. static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
  104. void *parg)
  105. {
  106. NDEF_SUPPORT *ndef_aux;
  107. if (!parg)
  108. return 0;
  109. ndef_aux = *(NDEF_SUPPORT **)parg;
  110. OPENSSL_free(ndef_aux->derbuf);
  111. ndef_aux->derbuf = NULL;
  112. *pbuf = NULL;
  113. *plen = 0;
  114. return 1;
  115. }
  116. static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
  117. void *parg)
  118. {
  119. NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
  120. if (!ndef_prefix_free(b, pbuf, plen, parg))
  121. return 0;
  122. OPENSSL_free(*pndef_aux);
  123. *pndef_aux = NULL;
  124. return 1;
  125. }
  126. static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
  127. {
  128. NDEF_SUPPORT *ndef_aux;
  129. unsigned char *p;
  130. int derlen;
  131. const ASN1_AUX *aux;
  132. ASN1_STREAM_ARG sarg;
  133. if (!parg)
  134. return 0;
  135. ndef_aux = *(NDEF_SUPPORT **)parg;
  136. aux = ndef_aux->it->funcs;
  137. /* Finalize structures */
  138. sarg.ndef_bio = ndef_aux->ndef_bio;
  139. sarg.out = ndef_aux->out;
  140. sarg.boundary = ndef_aux->boundary;
  141. if (aux->asn1_cb(ASN1_OP_STREAM_POST,
  142. &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
  143. return 0;
  144. derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
  145. p = OPENSSL_malloc(derlen);
  146. if (p == NULL)
  147. return 0;
  148. ndef_aux->derbuf = p;
  149. *pbuf = p;
  150. derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
  151. if (!*ndef_aux->boundary)
  152. return 0;
  153. *pbuf = *ndef_aux->boundary;
  154. *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
  155. return 1;
  156. }